{"id":26026905,"url":"https://github.com/martincastroalvarez/solidity-upgradeable-contract","last_synced_at":"2025-08-31T13:39:18.236Z","repository":{"id":277913072,"uuid":"933725927","full_name":"MartinCastroAlvarez/solidity-upgradeable-contract","owner":"MartinCastroAlvarez","description":"Upgradeable Solidity contract with access management.","archived":false,"fork":false,"pushed_at":"2025-02-16T23:24:33.000Z","size":2327,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-06T15:36:55.572Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MartinCastroAlvarez.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-16T14:59:12.000Z","updated_at":"2025-02-16T23:24:36.000Z","dependencies_parsed_at":"2025-02-17T00:23:35.640Z","dependency_job_id":"f9a5074f-310c-40ce-b316-c73dfe549f22","html_url":"https://github.com/MartinCastroAlvarez/solidity-upgradeable-contract","commit_stats":null,"previous_names":["martincastroalvarez/solidity-upgradeable-contract"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MartinCastroAlvarez/solidity-upgradeable-contract","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MartinCastroAlvarez%2Fsolidity-upgradeable-contract","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MartinCastroAlvarez%2Fsolidity-upgradeable-contract/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MartinCastroAlvarez%2Fsolidity-upgradeable-contract/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MartinCastroAlvarez%2Fsolidity-upgradeable-contract/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MartinCastroAlvarez","download_url":"https://codeload.github.com/MartinCastroAlvarez/solidity-upgradeable-contract/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MartinCastroAlvarez%2Fsolidity-upgradeable-contract/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272988782,"owners_count":25026959,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-31T02:00:09.071Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-06T15:29:40.852Z","updated_at":"2025-08-31T13:39:18.215Z","avatar_url":"https://github.com/MartinCastroAlvarez.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# solidity-upgradeable-contract\n\nUpgradeable Solidity contract with access management.\n\n![wallpaper.jpg](./wallpaper.jpg)\n\n## References\n\n- [Solidity Upgradeable Contracts](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable)\n- [Running Anvil](https://github.com/MartinCastroAlvarez/anvil-of-fury/tree/main)\n\n## Overview\n\n- [Manager.sol](./src/Manager.sol) is an upgradeable Solidity contract built with OpenZeppelin's upgradeable libraries that offers a secure and flexible solution for managing signature verifications. It combines a robust access control system, pausing functionality for emergencies, and upgradeability with state migration to ensure the contract remains secure and maintainable over time.\n- [Verifier.sol](./src/Verifier.sol) is a simple Solidity contract that allows to register and revoke signatures.\n- [Deploy.sol](./Deploy.sol) is a script that deploys the [Manager.sol](./src/Manager.sol) and [Verifier.sol](./src/Verifier.sol) contracts.\n- [test/Manager.t.sol](./test/Manager.t.sol) is a test file that tests the [Manager.sol](./src/Manager.sol) contract.\n- [test/Verifier.t.sol](./test/Verifier.t.sol) is a test file that tests the [Verifier.sol](./src/Verifier.sol) contract.\n\n#### Interfaces\n\n- The `Initializable` base contract is use to guarantee that a contract is only initialized once.\n- The `Upgradeable` base contract is use to guarantee that a contract is upgradeable.\n- The `AccessControl` base contract is use to manage access control.\n- The `Pausable` base contract is use to pause the contract in case of emergency.\n\n#### Access Control\n\nThe [Manager](./src/Manager.sol) contract implements a role-based access control system to restrict functionalities to authorized users. There are three primary roles:\n\n- **Admin (DEFAULT_ADMIN_ROLE):** Has full control over the contract, can execute all methods, and is the only role allowed to remove roles.\n- **Maintainer (MAINTAINER_ROLE):** Authorized to upgrade the contract and assign other maintainers.\n- **Authority (AUTHORITY_ROLE):** Empowered to set or update the verifier contract and assign other authorities.\n\n#### Upgradeability\n\nThe contract supports upgradeability via an upgrade function that can only be called by an Admin or a Maintainer. During an upgrade, the current state—specifically the verifier address and the verification counter—is migrated to a new contract instance through a defined migration interface. After upgrading, no further operations can be performed on the original contract, ensuring a secure transition.\n\n#### Pausability\n\nManager incorporates a pausability feature that allows an Admin to pause or unpause the contract in emergency scenarios. When paused, all functions—including verification, access control modifications, and upgrades—are disabled, safeguarding the contract from potential malicious activities or unforeseen issues until the situation is resolved.\n\n#### Verification\n\nThe contract performs batch verification of signatures by interacting with an external verifier contract. The `batchVerify` function processes an array of signatures for a given user, calling the verifier's `verify` method on each signature. Each successful verification increments a counter using SafeMath to prevent overflows, enabling accurate tracking of valid verifications.\n\n#### Error Handling\n\nRobust error handling is built into the contract to ensure that if any call fails—such as an invalid verifier address or an error during verification—the entire transaction is reverted. This mechanism prevents partial state updates and ensures the integrity and consistency of the contract's state under all conditions.\n\n## Setup\n\nStart Anvil:\n\n```bash\ncurl -L https://foundry.paradigm.xyz | bash\nfoundryup\nanvil\n```\n\nInstall Foundry dependencies:\n\n```bash\nforge install foundry-rs/forge-std\n```\n\nInstall OpenZeppelin dependencies:\n\n```bash\nforge install OpenZeppelin/openzeppelin-contracts\nforge install OpenZeppelin/openzeppelin-contracts-upgradeable\n```\n\n## Deployment\n\nTo test the [Manager](./src/Manager.sol) contract, run the following command:\n\n```bash\nforge test\n```\n\nResponse:\n\n```bash\n[...]\nRan 2 test suites in 298.44ms (2.46ms CPU time): 21 tests passed, 0 failed, 0 skipped (21 total tests)\n```\n\nNext, to deploy the [Manager](./src/Manager.sol) and [Verifier](./src/Verifier.sol) contracts, run the following command:\n\n```bash\nforge script ./Deploy.sol \\\n    --rpc-url http://127.0.0.1:8545 \\\n    --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \\\n    --broadcast\n```\n\nResponse:\n\n```bash\n[...]\nScript ran successfully.\n\n== Logs ==\n  Manager proxy deployed at: 0xc6e7DF5E7b4f2A278906862b61205850344D4e7d\n  Verifier proxy deployed at: 0x59b670e9fA9D0A427751Af201D676719a970857b\n[...]\n```\n\nExport the contract ABIs:\n\n```bash\ncat out/Manager.sol/Manager.json | jq -r '.abi' \u003e Manager.abi\ncat out/Verifier.sol/Verifier.json | jq -r '.abi' \u003e Verifier.abi\n```\n\n## Testing\n\nSet the env vars before running the tests:\n\n```bash\n# Update these with your proxy addresses from deployment\nexport MANAGER_ADDRESS=0xc6e7DF5E7b4f2A278906862b61205850344D4e7d\nexport VERIFIER_ADDRESS=0x59b670e9fA9D0A427751Af201D676719a970857b\nexport ADMIN_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\nexport ADMIN_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80\nexport ETHEREUM_RPC_URL=http://127.0.0.1:8545\nexport AUTHORITY_ROLE=$(cast keccak \"AUTHORITY_ROLE\")\nexport USER_ADDRESS=0x742d35cc6634c0532925a3b844f51317abc046cd\nexport USER_SIGNATURE=0x0000000000000000000000000000000000000000000000000000000000000000\n```\n\nGrant AUTHORITY_ROLE to admin (needed to set verifier):\n\n```bash\ncast send $MANAGER_ADDRESS \"assignRole(bytes32,address)\" $AUTHORITY_ROLE $ADMIN_ADDRESS \\\n    --private-key $ADMIN_PRIVATE_KEY --rpc-url $ETHEREUM_RPC_URL\n```\n\nPause the Manager contract:\n\n```bash\ncast send $MANAGER_ADDRESS \"pause()\" \\\n    --private-key $ADMIN_PRIVATE_KEY --rpc-url $ETHEREUM_RPC_URL\n```\n\nVerify the contract is paused:\n\n```bash\ncast call $MANAGER_ADDRESS \"paused()\" --rpc-url $ETHEREUM_RPC_URL\n```\n\nUnpause the Manager contract:\n\n```bash\ncast send $MANAGER_ADDRESS \"unpause()\" \\\n    --private-key $ADMIN_PRIVATE_KEY --rpc-url $ETHEREUM_RPC_URL\n```\n\nSet the Verifier contract in the Manager:\n\n```bash\ncast send $MANAGER_ADDRESS \"setVerifier(address)\" $VERIFIER_ADDRESS \\\n    --private-key $ADMIN_PRIVATE_KEY --rpc-url $ETHEREUM_RPC_URL\n```\n\nVerify the verifier address is set correctly:\n\n```bash\ncast call $MANAGER_ADDRESS \"getVerifier()\" --rpc-url $ETHEREUM_RPC_URL\n```\n\nRegister a signature in the Verifier contract:\n\n```bash\ncast send $VERIFIER_ADDRESS \"registerSignature(address,bytes32)\" $USER_ADDRESS $USER_SIGNATURE \\\n    --private-key $ADMIN_PRIVATE_KEY --rpc-url $ETHEREUM_RPC_URL\n```\n\nVerify the signature through the Manager contract:\n\n```bash\n# Create an array with one signature for batch verification\nexport SIGNATURES=\"[$USER_SIGNATURE]\"\ncast send $MANAGER_ADDRESS \"batchVerify(address,bytes32[])\" $USER_ADDRESS $SIGNATURES \\\n    --private-key $ADMIN_PRIVATE_KEY --rpc-url $ETHEREUM_RPC_URL\n```\n\nCheck the verification counter (should be 1):\n\n```bash\ncast call $MANAGER_ADDRESS \"getVerificationCounter()\" --rpc-url $ETHEREUM_RPC_URL\n```\n\nThe counter value will be returned in hex format. To convert it to decimal:\n\n```bash\ncast --to-dec $(cast call $MANAGER_ADDRESS \"getVerificationCounter()\" --rpc-url $ETHEREUM_RPC_URL)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartincastroalvarez%2Fsolidity-upgradeable-contract","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartincastroalvarez%2Fsolidity-upgradeable-contract","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartincastroalvarez%2Fsolidity-upgradeable-contract/lists"}