-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support automatic verification for @openzeppelin/hardhat-upgrades (#176)
This PR implements the support for manual and automatic verification of proxies, their implementations and all related contracts deployed with `@openzeppelin/hardhat-upgrades` plugin. This PR also updates the `examples/contract-verification` folder with example usages of this feature.
- Loading branch information
Showing
28 changed files
with
8,337 additions
and
1,356 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@tenderly/hardhat-tenderly": minor | ||
"tenderly": minor | ||
--- | ||
|
||
Implement manual and automatic verification of proxies deployed with `@openzeppelin/hardhat-upgrades`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; | ||
|
||
contract VotingLogic is Initializable { | ||
string private name; | ||
|
||
// Struct to hold poll data | ||
struct Poll { | ||
string[] options; // Array of options for the poll | ||
mapping(string => uint) votes; // Mapping of option to vote count | ||
bool exists; // Flag to check if the poll exists | ||
} | ||
|
||
// Mapping from poll ID to Poll struct | ||
mapping(bytes32 => Poll) public polls; | ||
|
||
// Event emitted when a new poll is created | ||
event PollCreated(bytes32 pollId); | ||
|
||
// Event emitted when a vote is cast | ||
event VoteCast(bytes32 pollId, string option); | ||
|
||
function initialize() public initializer { | ||
name = "VotingLogic-V9"; | ||
} | ||
|
||
/** | ||
* @dev Create a new poll with given options. | ||
* @param pollId Unique identifier for the poll | ||
* @param options Array of options for the poll | ||
*/ | ||
function createPoll(bytes32 pollId, string[] memory options) public { | ||
require(options.length > 1, "There must be at least two options."); | ||
require(!polls[pollId].exists, "Poll already exists."); | ||
|
||
Poll storage newPoll = polls[pollId]; | ||
for (uint i = 0; i < options.length; i++) { | ||
newPoll.options.push(options[i]); | ||
newPoll.votes[options[i]] = 0; | ||
} | ||
newPoll.exists = true; | ||
|
||
emit PollCreated(pollId); | ||
} | ||
|
||
/** | ||
* @dev Cast a vote in a specific poll. | ||
* @param pollId Unique identifier for the poll | ||
* @param option The option to vote for | ||
*/ | ||
function vote(bytes32 pollId, string memory option) public { | ||
require(polls[pollId].exists, "Poll does not exist."); | ||
require(polls[pollId].votes[option] >= 0, "Invalid option."); | ||
|
||
polls[pollId].votes[option]++; | ||
|
||
emit VoteCast(pollId, option); | ||
} | ||
|
||
/** | ||
* @dev Get the results of a poll. | ||
* @param pollId Unique identifier for the poll | ||
* @return An array of options and their respective vote counts | ||
*/ | ||
function getResults(bytes32 pollId) public view returns (string[] memory, uint[] memory) { | ||
require(polls[pollId].exists, "Poll does not exist."); | ||
|
||
Poll storage poll = polls[pollId]; | ||
uint[] memory voteCounts = new uint[](poll.options.length); | ||
|
||
for (uint i = 0; i < poll.options.length; i++) { | ||
voteCounts[i] = poll.votes[poll.options[i]]; | ||
} | ||
|
||
return (poll.options, voteCounts); | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
examples/contract-verification/contracts/VotingLogicUpgradeable.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; | ||
import "hardhat-deploy/solc_0.8/openzeppelin/access/Ownable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; | ||
|
||
contract VotingLogicUpgradeable is Initializable, UUPSUpgradeable, OwnableUpgradeable { | ||
string private name; | ||
|
||
// Struct to hold poll data | ||
struct Poll { | ||
string[] options; // Array of options for the poll | ||
mapping(string => uint) votes; // Mapping of option to vote count | ||
bool exists; // Flag to check if the poll exists | ||
} | ||
|
||
// Mapping from poll ID to Poll struct | ||
mapping(bytes32 => Poll) public polls; | ||
|
||
// Event emitted when a new poll is created | ||
event PollCreated(bytes32 pollId); | ||
|
||
// Event emitted when a vote is cast | ||
event VoteCast(bytes32 pollId, string option); | ||
|
||
function initialize() public initializer { | ||
name = "VotingLogic-V10"; | ||
} | ||
|
||
/** | ||
* @dev Create a new poll with given options. | ||
* @param pollId Unique identifier for the poll | ||
* @param options Array of options for the poll | ||
*/ | ||
function createPoll(bytes32 pollId, string[] memory options) public { | ||
require(options.length > 1, "There must be at least two options."); | ||
require(!polls[pollId].exists, "Poll already exists."); | ||
|
||
Poll storage newPoll = polls[pollId]; | ||
for (uint i = 0; i < options.length; i++) { | ||
newPoll.options.push(options[i]); | ||
newPoll.votes[options[i]] = 0; | ||
} | ||
newPoll.exists = true; | ||
|
||
emit PollCreated(pollId); | ||
} | ||
|
||
/** | ||
* @dev Cast a vote in a specific poll. | ||
* @param pollId Unique identifier for the poll | ||
* @param option The option to vote for | ||
*/ | ||
function vote(bytes32 pollId, string memory option) public { | ||
require(polls[pollId].exists, "Poll does not exist."); | ||
require(polls[pollId].votes[option] >= 0, "Invalid option."); | ||
|
||
polls[pollId].votes[option]++; | ||
|
||
emit VoteCast(pollId, option); | ||
} | ||
|
||
/** | ||
* @dev Get the results of a poll. | ||
* @param pollId Unique identifier for the poll | ||
* @return An array of options and their respective vote counts | ||
*/ | ||
function getResults(bytes32 pollId) public view returns (string[] memory, uint[] memory) { | ||
require(polls[pollId].exists, "Poll does not exist."); | ||
|
||
Poll storage poll = polls[pollId]; | ||
uint[] memory voteCounts = new uint[](poll.options.length); | ||
|
||
for (uint i = 0; i < poll.options.length; i++) { | ||
voteCounts[i] = poll.votes[poll.options[i]]; | ||
} | ||
|
||
return (poll.options, voteCounts); | ||
} | ||
|
||
function _authorizeUpgrade(address newImplementation) internal override onlyOwner { } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { | ||
deployTransparentUpgradeableProxy, | ||
deployUUPSProxy, | ||
deployBeaconProxy, | ||
} from "./deployment"; | ||
|
||
export async function main() { | ||
// TransparentUpgradeableProxy | ||
// The plugin will automatically verify the proxy, implementation and all the related contracts on deployment. | ||
await deployTransparentUpgradeableProxy(); | ||
|
||
// UUPSProxy | ||
// The plugin will automatically verify the proxy, implementation and all the related contracts on deployment. | ||
await deployUUPSProxy(); | ||
|
||
// Beacon Proxy | ||
// The plugin will automatically verify the proxy, implementation and all the related contracts on deployment. | ||
await deployBeaconProxy(); | ||
} | ||
|
||
main().catch((error) => { | ||
console.error(error); | ||
process.exitCode = 1; | ||
}); |
Oops, something went wrong.