diff --git a/.gitleaksignore b/.gitleaksignore
index ecaf64d8..d8e0189d 100644
--- a/.gitleaksignore
+++ b/.gitleaksignore
@@ -135,4 +135,58 @@ f78d4539c80abb33ea04dce4d561af5302033235:scripts/deployment/staking/globals_sepo
9fa4b1fb81ba553ed48ef4a9b22c53ecdf4d2242:scripts/deployment/staking/globals_sepolia.json:generic-api-key:1
9fa4b1fb81ba553ed48ef4a9b22c53ecdf4d2242:scripts/deployment/staking/globals_sepolia.json:generic-api-key:2
001d71fc7c216c593faebdd3d6f353efaf80605f:scripts/deployment/staking/globals_sepolia.json:generic-api-key:1
-001d71fc7c216c593faebdd3d6f353efaf80605f:scripts/deployment/staking/globals_sepolia.json:generic-api-key:2
\ No newline at end of file
+001d71fc7c216c593faebdd3d6f353efaf80605f:scripts/deployment/staking/globals_sepolia.json:generic-api-key:2
+ea6713128995ac18f3911c0214163e2b82896a7f:scripts/deployment/globals_mainnet.json:generic-api-key:1
+ea6713128995ac18f3911c0214163e2b82896a7f:scripts/deployment/globals_mainnet.json:generic-api-key:2
+1a7a855a853d2bc21e1e9178754a22dae54439f3:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1
+1a7a855a853d2bc21e1e9178754a22dae54439f3:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2
+3c5c0643bfa60605d7b91eb4b7a4b80c6f7a1b43:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1
+3c5c0643bfa60605d7b91eb4b7a4b80c6f7a1b43:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2
+b17bdd0ebae90b769b8756da81d831a70fcb4af3:scripts/deployment/globals_mainnet.json:generic-api-key:1
+b17bdd0ebae90b769b8756da81d831a70fcb4af3:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1
+b17bdd0ebae90b769b8756da81d831a70fcb4af3:scripts/deployment/globals_mainnet.json:generic-api-key:2
+b17bdd0ebae90b769b8756da81d831a70fcb4af3:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2
+c5ba11d1b46a6fa9644c0de28b4b0f7b154156ee:scripts/deployment/globals_mainnet.json:generic-api-key:1
+c5ba11d1b46a6fa9644c0de28b4b0f7b154156ee:scripts/deployment/globals_mainnet.json:generic-api-key:2
+c5ba11d1b46a6fa9644c0de28b4b0f7b154156ee:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1
+c5ba11d1b46a6fa9644c0de28b4b0f7b154156ee:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2
+7cf3cd1c5fa705f82f0f33c90538fa6e6892af5b:scripts/deployment/globals_mainnet.json:generic-api-key:1
+7cf3cd1c5fa705f82f0f33c90538fa6e6892af5b:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1
+7cf3cd1c5fa705f82f0f33c90538fa6e6892af5b:scripts/deployment/globals_mainnet.json:generic-api-key:2
+7cf3cd1c5fa705f82f0f33c90538fa6e6892af5b:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2
+38ff93e8e51ef86b6c46872b12e27f67152ec07a:scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json:generic-api-key:1
+38ff93e8e51ef86b6c46872b12e27f67152ec07a:scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json:generic-api-key:2
+38ff93e8e51ef86b6c46872b12e27f67152ec07a:scripts/deployment/staking/wormhole/globals_celo_mainnet.json:generic-api-key:1
+38ff93e8e51ef86b6c46872b12e27f67152ec07a:scripts/deployment/staking/wormhole/globals_celo_mainnet.json:generic-api-key:2
+cfe4b8064bfda91d83bd5bdc5af44f2155859ef3:scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json:generic-api-key:1
+cfe4b8064bfda91d83bd5bdc5af44f2155859ef3:scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json:generic-api-key:2
+cfe4b8064bfda91d83bd5bdc5af44f2155859ef3:scripts/deployment/staking/wormhole/globals_celo_mainnet.json:generic-api-key:1
+cfe4b8064bfda91d83bd5bdc5af44f2155859ef3:scripts/deployment/staking/wormhole/globals_celo_mainnet.json:generic-api-key:2
+e09cdb5c34a402545d5a67d65ea31760f7c0fd19:scripts/deployment/globals_mainnet.json:generic-api-key:1
+e09cdb5c34a402545d5a67d65ea31760f7c0fd19:scripts/deployment/globals_mainnet.json:generic-api-key:2
+02f626605f59ee89a44152d2d8723c848174e44:scripts/deployment/staking/globals_sepolia.json:generic-api-key:2
+f02f626605f59ee89a44152d2d8723c848174e44:scripts/deployment/globals_mainnet.json:generic-api-key:2
+a1fb94f332608c58c44aed99a08fea5fb08fc6ed:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1
+b92c814bbbab19139c4d40d31f7d0394e2796d0f:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1
+d3c5ea3ef6d62f5cfb51d2485b74133f84d40f7d:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1
+d79d6210c89d103448e32b7c915903c8a8b8d87a:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1
+d79d6210c89d103448e32b7c915903c8a8b8d87a:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1
+e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/globals_mainnet.json:generic-api-key:1
+e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1
+e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1
+e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/globals_sepolia.json:generic-api-key:1
+a1fb94f332608c58c44aed99a08fea5fb08fc6ed:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2
+b92c814bbbab19139c4d40d31f7d0394e2796d0f:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2
+d3c5ea3ef6d62f5cfb51d2485b74133f84d40f7d:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2
+d79d6210c89d103448e32b7c915903c8a8b8d87a:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2
+d79d6210c89d103448e32b7c915903c8a8b8d87a:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2
+e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/globals_mainnet.json:generic-api-key:2
+e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2
+e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2
+e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/globals_sepolia.json:generic-api-key:2
+3068b0eefad400612f18c193fa62e11974c0fbd5:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1
+3068b0eefad400612f18c193fa62e11974c0fbd5:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2
+b616524545db2768fb9a3772ffd05c6e0a7f2d8b:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1
+b616524545db2768fb9a3772ffd05c6e0a7f2d8b:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2
+5e43d545806f8e2d6e8ffd8190d7d704bf663d5f:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1
+5e43d545806f8e2d6e8ffd8190d7d704bf663d5f:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 259faf48..2913eb37 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,11 +4,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Common Changelog](https://common-changelog.org).
+[1.2.2]: https://github.com/valory-xyz/autonolas-tokenomics/compare/v1.0.3...v1.2.2
[1.0.3]: https://github.com/valory-xyz/autonolas-tokenomics/compare/v1.0.2...v1.0.3
[1.0.2]: https://github.com/valory-xyz/autonolas-tokenomics/compare/v1.0.1...v1.0.2
[1.0.1]: https://github.com/valory-xyz/autonolas-tokenomics/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/valory-xyz/autonolas-tokenomics/releases/tag/v1.0.0
+## [1.2.2] - 2024-07-29
+
+### Changed
+
+- Introducing Service Staking according to [PoAA Whitepaper](https://staking.olas.network/poaa-whitepaper.pdf)
+- Refactored and re-deployed `Tokenomics.sol` and `Dispenser.sol` to address service staking inflation and claiming capability ([#156](https://github.com/valory-xyz/autonolas-registries/pull/156)), with the subsequent internal audit ([#168](https://github.com/valory-xyz/autonolas-registries/pull/168))
+- Created and deployed `ArbitrumDepositProcessorL1.sol`, `ArbitrumTargetDispenserL2.sol`, `DefaultDepositProcessorL1.sol`, `DefaultTargetDispenserL2.sol`, `EthereumDepositProcessor.sol`, `GnosisDepositProcessorL1.sol` , `GnosisTargetDispenserL2.sol`, `OptimismDepositProcessorL1.sol`, `OptimismTargetDispenserL2.sol`, `PolygonDepositProcessorL1.sol`, `PolygonTargetDispenserL2.sol`, `WormholeDepositProcessorL1.sol`, and `WormholeTargetDispenserL2.sol` contracts
+- Participated in a complete [C4R audit competition](https://github.com/code-423n4/2024-05-olas-findings) and addressed findings
+
## [1.0.3] - 2023-10-05
_No bytecode changes_.
diff --git a/abis/0.8.25/Dispenser.json b/abis/0.8.25/Dispenser.json
index 7088a562..475842a3 100644
--- a/abis/0.8.25/Dispenser.json
+++ b/abis/0.8.25/Dispenser.json
@@ -213,6 +213,19 @@
"name": "ZeroValue",
"type": "error"
},
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "nomineeHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "AddNomineeHash",
+ "type": "event"
+ },
{
"anonymous": false,
"inputs": [
@@ -233,6 +246,18 @@
"internalType": "uint256",
"name": "topUp",
"type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256[]",
+ "name": "unitTypes",
+ "type": "uint256[]"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256[]",
+ "name": "unitIds",
+ "type": "uint256[]"
}
],
"name": "IncentivesClaimed",
@@ -264,6 +289,19 @@
"name": "PauseDispenser",
"type": "event"
},
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "nomineeHash",
+ "type": "bytes32"
+ }
+ ],
+ "name": "RemoveNomineeHash",
+ "type": "event"
+ },
{
"anonymous": false,
"inputs": [
@@ -311,6 +349,67 @@
"name": "account",
"type": "address"
},
+ {
+ "indexed": false,
+ "internalType": "uint256[]",
+ "name": "chainIds",
+ "type": "uint256[]"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes32[][]",
+ "name": "stakingTargets",
+ "type": "bytes32[][]"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256[][]",
+ "name": "stakingIncentives",
+ "type": "uint256[][]"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalStakingIncentive",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalTransferAmount",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalReturnAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakingIncentivesBatchClaimed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "chainId",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "stakingTarget",
+ "type": "bytes32"
+ },
{
"indexed": false,
"internalType": "uint256",
@@ -990,8 +1089,8 @@
"type": "function"
}
],
- "bytecode": "0x610120604052348015610010575f80fd5b50604051614b01380380614b0183398101604081905261002f91610226565b6002805460ff60a01b1933166001600160a81b031990911617600160a01b1760ff60a81b1916600160a91b1790556001600160a01b038916158061007a57506001600160a01b038816155b8061008c57506001600160a01b038716155b8061009e57506001600160a01b038616155b806100a7575084155b156100c55760405163d92e233d60e01b815260040160405180910390fd5b8315806100d0575082155b806100d9575081155b806100e2575080155b1561010057604051637c946ed760e01b815260040160405180910390fd5b61ffff82111561013357604051637ae5968560e01b81526004810183905261ffff60248201526044015b60405180910390fd5b6001600160601b0381111561016b57604051637ae5968560e01b8152600481018290526001600160601b03602482015260440161012a565b6001600160a01b0398891660c05260038054988a166001600160a01b0319998a1617905560048054978a16978916979097179096556005805495909816949096169390931790955560e0819052604080518082018252828152466020918201908152825180830194909452518383015281518084038301815260609093019091528151910120610100525f9390935560019290925560805260a0526102a5565b80516001600160a01b0381168114610221575f80fd5b919050565b5f805f805f805f805f6101208a8c03121561023f575f80fd5b6102488a61020b565b985061025660208b0161020b565b975061026460408b0161020b565b965061027260608b0161020b565b955060808a0151945060a08a0151935060c08a0151925060e08a015191506101008a015190509295985092959850929598565b60805160a05160c05160e0516101005161479361036e5f395f81816103450152818161141401528181611cf50152611d9c01525f8181610671015281816114470152818161169b015281816116cf01528181611d2c01528181611ec60152818161318e01526131f401525f81816101ef015281816109c201528181610ac901528181610e4901528181610f98015281816126a3015281816127b001528181612ae4015261354c01525f818161063e01526118a401525f818161029c015261187001526147935ff3fe6080604052600436106101da575f3560e01c806379bc81dd116100fd578063bc7d5c5c11610092578063dcb5ccc411610062578063dcb5ccc4146105f9578063e09177781461062d578063e6be59e714610660578063f4da12ba14610693575f80fd5b8063bc7d5c5c14610568578063d529779314610587578063d7accbcc146105a6578063d8bf69bf146105da575f80fd5b80639649a35c116100cd5780639649a35c146104eb578063a5edd4fc146104ff578063a6f9dae11461051e578063bb78678f1461053d575f80fd5b806379bc81dd1461046e5780638513e77d1461048d5780638833c205146104b85780638da5cb5b146104cc575f80fd5b80633c18d1dd1161017357806361d027b31161014357806361d027b3146103d257806363096509146103f157806363c4d28e14610410578063777e49c91461042f575f80fd5b80633c18d1dd146103345780634ac7251d146103675780635a55a482146103865780635c975abb146103a5575f80fd5b80632ad923dc116101ae5780632ad923dc146102cc5780632c0f3f29146102f757806334be5af41461030c5780633907196c14610321575f80fd5b806231d115146101de5780630d17db111461022e5780630d3241ee1461026c5780632a3bb6931461028b575b5f80fd5b3480156101e9575f80fd5b506102117f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610239575f80fd5b5061025c610248366004613c36565b600a6020525f908152604090205460ff1681565b6040519015158152602001610225565b348015610277575f80fd5b50600554610211906001600160a01b031681565b348015610296575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610225565b3480156102d7575f80fd5b506102be6102e6366004613c36565b60066020525f908152604090205481565b61030a610305366004613cfe565b6106a7565b005b348015610317575f80fd5b506102be60015481565b61030a61032f366004613e5e565b610be6565b34801561033f575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b348015610372575f80fd5b50600354610211906001600160a01b031681565b348015610391575f80fd5b5061030a6103a0366004613fde565b611148565b3480156103b0575f80fd5b506002546103c590600160a81b900460ff1681565b604051610225919061401b565b3480156103dd575f80fd5b50600454610211906001600160a01b031681565b3480156103fc575f80fd5b5061030a61040b366004614041565b611312565b34801561041b575f80fd5b5061030a61042a366004613c36565b6113d1565b34801561043a575f80fd5b5061044e610449366004614066565b611654565b604080519485526020850193909352918301526060820152608001610225565b348015610479575f80fd5b5061030a610488366004613fde565b611b99565b348015610498575f80fd5b506102be6104a7366004613c36565b60076020525f908152604090205481565b3480156104c3575f80fd5b506102be5f5481565b3480156104d7575f80fd5b50600254610211906001600160a01b031681565b3480156104f6575f80fd5b5061030a611ca8565b34801561050a575f80fd5b5061030a610519366004613c36565b61204a565b348015610529575f80fd5b5061030a6105383660046140b0565b6121ed565b348015610548575f80fd5b506102be610557366004613c36565b60096020525f908152604090205481565b348015610573575f80fd5b5061030a6105823660046140c9565b6122aa565b348015610592575f80fd5b5061030a6105a13660046140e9565b61235a565b3480156105b1575f80fd5b506105c56105c0366004614129565b6124c8565b60408051928352602083019190915201610225565b3480156105e5575f80fd5b5061030a6105f4366004614189565b6128f9565b348015610604575f80fd5b50610211610613366004613c36565b60086020525f90815260409020546001600160a01b031681565b348015610638575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066b575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561069e575f80fd5b506102be612a5c565b6002546001600160a01b90910460ff1611156106d6576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f83900361070a57604051637c946ed760e01b815260040160405180910390fd5b5f82900361072b5760405163d92e233d60e01b815260040160405180910390fd5b5f548085111561075d57604051637ae5968560e01b815260048101869052602481018290526044015b60405180910390fd5b60028054600160a81b900460ff169081600381111561077e5761077e614007565b148061079b5750600381600381111561079957610799614007565b145b8061081257506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156107e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061080b919061423c565b60ff166002145b15610830576040516313d0ff5960e31b815260040160405180910390fd5b5f8581526008602090815260408083205481517fa8b2ae0200000000000000000000000000000000000000000000000000000000815291516001600160a01b039091169392849263a8b2ae0292600480830193928290030181865afa15801561089b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bf9190614255565b90505f805f806108d18c8c8c88611654565b5f81815260066020526040902082905592965090945092509050821561094b57600354604051635e148f0960e11b8152600481018590526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015610934575f80fd5b505af1158015610946573d5f803e3d5ffd5b505050505b5f8415610b8157505f8b815260096020526040902054849080156109a5578181106109845761097a8282614280565b90505f9150610994565b61098e8183614280565b91505f90505b5f8d81526009602052604090208190555b8115610b72576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610a0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a339190614255565b60048054604051637ff796ab60e01b815230928101929092525f6024830152604482018690529192506001600160a01b0390911690637ff796ab906064016020604051808303815f875af1158015610a8d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab19190614299565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610b16573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3a9190614255565b610b449190614280565b9050828114610b705760405163312b003360e01b81526004810182905260248101849052604401610754565b505b610b7f8d8d888e86612a88565b505b604080518681526020810183905290810185905233907f02b21954a7bf2d6a171db9a87b430a3723605c554db00adcb95b26ce8464f2809060600160405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050505050565b6002546001600160a01b90910460ff161115610c15576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179055610c3484848484612c86565b5f5480861115610c6157604051637ae5968560e01b81526004810187905260248101829052604401610754565b60028054600160a81b900460ff1690816003811115610c8257610c82614007565b1480610c9f57506003816003811115610c9d57610c9d614007565b145b80610d1657506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015610ceb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d0f919061423c565b60ff166002145b15610d34576040516313d0ff5960e31b815260040160405180910390fd5b6060806060610d448a8a8a612f84565b825192955090935091505f9084906002908110610d6357610d636142b8565b60200260200101511115610def5760035483516001600160a01b039091169063bc291e129085906002908110610d9b57610d9b6142b8565b60200260200101516040518263ffffffff1660e01b8152600401610dc191815260200190565b5f604051808303815f87803b158015610dd8575f80fd5b505af1158015610dea573d5f803e3d5ffd5b505050505b5f835f81518110610e0257610e026142b8565b60200260200101511115611086575f83600181518110610e2457610e246142b8565b60200260200101511115611078576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610e96573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eba9190614255565b60045485519192506001600160a01b031690637ff796ab9030905f9088906001908110610ee957610ee96142b8565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303815f875af1158015610f5c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f809190614299565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610fe5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110099190614255565b6110139190614280565b905083600181518110611028576110286142b8565b6020026020010151811461107657808460018151811061104a5761104a6142b8565b602002602001015160405163312b003360e01b8152600401610754929190918252602082015260400190565b505b6110868989848a858b6134de565b336001600160a01b03167f02b21954a7bf2d6a171db9a87b430a3723605c554db00adcb95b26ce8464f280845f815181106110c3576110c36142b8565b6020026020010151856001815181106110de576110de6142b8565b6020026020010151866002815181106110f9576110f96142b8565b6020026020010151604051611121939291909283526020830191909152604082015260600190565b60405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050565b6002546001600160a01b031633146111885760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b821580611193575081155b8061119c575080155b156111ba57604051637c946ed760e01b815260040160405180910390fd5b4683036111dd57604051633881b68960e01b815260048101849052602401610754565b5f838152600960205260408120546111f69084906142cc565b90506bffffffffffffffffffffffff81111561123a57604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f8481526009602090815260408083208490556008909152908190205490517fac65ded2000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690819063ac65ded2906024015f604051808303815f87803b1580156112b1575f80fd5b505af11580156112c3573d5f803e3d5ffd5b505060408051888152602081018890529081018590528592507f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97591506060015b60405180910390a25050505050565b6002546001600160a01b031633146113525760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b600280548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16600160a81b83600381111561139257611392614007565b02179055507fa814f27828c0243d429ea8c7033cb10f0c825b9466fdc04f63e0cca26c28eb8a816040516113c6919061401b565b60405180910390a150565b6005546001600160a01b031633146114115760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b807f00000000000000000000000000000000000000000000000000000000000000000361147357604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b600354604080517f14b19c5a00000000000000000000000000000000000000000000000000000000815290515f926001600160a01b0316916314b19c5a9160048083019260209291908290030181865afa1580156114d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114f791906142df565b60035463ffffffff9190911691505f906001600160a01b031663d4ee9f8d611520600185614280565b6040518263ffffffff1660e01b815260040161153e91815260200190565b602060405180830381865afa158015611559573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061157d9190614255565b90505f60035f9054906101000a90046001600160a01b03166001600160a01b031663d2b3996f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f491906142df565b63ffffffff1690505f62093a8061160b83856142cc565b6116159190614280565b905080421061164057604051637ae5968560e01b815242600482015260248101829052604401610754565b5050505f9182526007602052604090912055565b5f805f80865f0361167857604051637c946ed760e01b815260040160405180910390fd5b5f8690036116995760405163d92e233d60e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000086036116fb57604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5060408051808201825286815260209081018881528251808301899052905181840152825180820384018152606090910190925281519101205f61173f828a613ae7565b6005546040516317d5e89d60e31b8152600481018b9052602481018c90529195509192506001600160a01b039091169063beaf44e8906044015f604051808303815f87803b15801561178f575f80fd5b505af11580156117a1573d5f803e3d5ffd5b5083925050505b83811015611b8c575f818152600a602052604090205460ff16611b8457600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa15801561180c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611830919061431d565b606081015190915060ff16156118cf57604081015161ffff16158015611866575060208101516bffffffffffffffffffffffff16155b156118ca5761ffff7f00000000000000000000000000000000000000000000000000000000000000001660408201526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660208201525b6118d5565b50611b84565b60035460405163d4ee9f8d60e01b8152600481018490525f916001600160a01b03169063d4ee9f8d90602401602060405180830381865afa15801561191c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119409190614255565b600554604051630c88d47f60e41b8152600481018d9052602481018e9052604481018390529192505f9182916001600160a01b03169063c88d47f0906064016040805180830381865afa158015611999573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119bd91906143a0565b91509150805f03611a05575f858152600a60205260409020805460ff1916600117905583516119fa906bffffffffffffffffffffffff168a6142cc565b985050505050611b84565b83515f9081906bffffffffffffffffffffffff168184821115611a3257611a2c8583614280565b90508491505b6040880151611a4b9061ffff16655af3107a40006143c2565b861015611a8157670de0b6b3a764000086611a6684846142cc565b611a7091906143c2565b611a7a91906143ed565b9250611b6f565b670de0b6b3a7640000611a9487846143c2565b611a9e91906143ed565b9350670de0b6b3a7640000611ab387836143c2565b611abd91906143ed565b925087602001516bffffffffffffffffffffffff16915081841115611af657611ae68285614280565b611af090846142cc565b92508193505b60128f1015611b62575f8f6012611b0d9190614280565b611b1890600a6144e0565b611b2290866143ed565b90508f6012611b319190614280565b611b3c90600a6144e0565b611b4690826143c2565b9050611b528186614280565b611b5c90856142cc565b90945092505b611b6c848f6142cc565b9d505b611b79838e6142cc565b9c5050505050505050505b6001016117a8565b5050945094509450949050565b5f838152600860205260409020546001600160a01b0316338114611bfa576040517fdeeeedec0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0382166024820152604401610754565b5f84815260096020526040812054611c139085906142cc565b90506bffffffffffffffffffffffff811115611c5757604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f85815260096020908152604091829020839055815187815290810186905290810182905283907f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97590606001611303565b6002546001600160a01b90910460ff161115611cd7576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f80548190611d1a907f000000000000000000000000000000000000000000000000000000000000000090613ae7565b6005546040516317d5e89d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201529294509092506001600160a01b03169063beaf44e8906044015f604051808303815f87803b158015611d86575f80fd5b505af1158015611d98573d5f803e3d5ffd5b50507f00000000000000000000000000000000000000000000000000000000000000005f90815260066020526040812084905591508390505b82811015611f8857600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611e20573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e44919061431d565b60035460405163d4ee9f8d60e01b8152600481018590529192505f916001600160a01b039091169063d4ee9f8d90602401602060405180830381865afa158015611e90573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eb49190614255565b600554604051630c88d47f60e41b81527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604481018390529192505f916001600160a01b039091169063c88d47f0906064016040805180830381865afa158015611f2b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f4f91906143a0565b508351909150611f6e9082906bffffffffffffffffffffffff166143c2565b611f7890866142cc565b9450505050806001019050611dd1565b50611f9b670de0b6b3a7640000826143ed565b90508015611ffd57600354604051635e148f0960e11b8152600481018390526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015611fe6575f80fd5b505af1158015611ff8573d5f803e3d5ffd5b505050505b60405181815233907f2a8de497d698d6869cb0844411788378e76214d03a541eec6ba514b795d9f42e9060200160405180910390a250506002805460ff60a01b1916600160a01b17905550565b6005546001600160a01b0316331461208a5760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b60028054600160a81b900460ff16908160038111156120ab576120ab614007565b14806120c8575060038160038111156120c6576120c6614007565b145b8061213f57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015612114573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612138919061423c565b60ff166002145b1561215d576040516313d0ff5960e31b815260040160405180910390fd5b60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121d191906142df565b5f9283526006602052604090922063ffffffff90921690915550565b6002546001600160a01b0316331461222d5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b0381166122545760405163d92e233d60e01b815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b905f90a250565b6002546001600160a01b031633146122ea5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b8115806122f5575080155b1561231357604051637c946ed760e01b815260040160405180910390fd5b5f829055600181905560408051838152602081018390527f61f6c4cc9665a257352c0b46189ffc2ae6fbbc11e155ff20901217ff203a517e91015b60405180910390a15050565b6002546001600160a01b0316331461239a5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b038316156123fd576003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385169081179091556040517f4672fe7e13cfb163442d0b729b5733fb3efafc66cbe3677eac9940eb41c284c2905f90a25b6001600160a01b03821615612460576004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040517f7dae230f18360d76a040c81f050aa14eb9d6dc7901b20fc5d855e2a20fe814d1905f90a25b6001600160a01b038116156124c3576005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f04a606379838ed6fc83fd189eea9d1835b5eff05035c4b74622911ea2ae6b217905f90a25b505050565b5f806001600260149054906101000a900460ff1660ff1611156124fe576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179081905560ff600160a81b90910416600181600381111561253257612532614007565b148061254f5750600381600381111561254d5761254d614007565b145b806125c657506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af115801561259b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125bf919061423c565b60ff166002145b156125e4576040516313d0ff5960e31b815260040160405180910390fd5b6003546040517f2e070f540000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632e070f549061263190339089908990600401614525565b60408051808303815f875af115801561264c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061267091906143a0565b90935091505f8061268184866142cc565b1115612859575f8315612717576040516370a0823160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156126f0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127149190614255565b90505b60048054604051637ff796ab60e01b8152339281019290925260248201879052604482018690526001600160a01b031690637ff796ab906064016020604051808303815f875af115801561276d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127919190614299565b91508315612857576040516370a0823160e01b815233600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156127fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128219190614255565b61282b9190614280565b90508381146128575760405163312b003360e01b81526004810182905260248101859052604401610754565b505b806128a0576040517f942dc9da0000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606401610754565b604080518581526020810185905233917f928890dff971de1394b7440848938a868d83445d2f7fb4b07938ae626c7cb130910160405180910390a250506002805460ff60a01b1916600160a01b17905590939092509050565b6002546001600160a01b031633146129395760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b8151158061294957508051825114155b1561297457815181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f5b8151811015612a2a57818181518110612991576129916142b8565b60200260200101515f036129b857604051637c946ed760e01b815260040160405180910390fd5b8281815181106129ca576129ca6142b8565b602002602001015160085f8484815181106129e7576129e76142b8565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001019050612976565b507fe87460f6c400fa0166984512586d7bdf03a3230bbadf9651f27f08716dd77fa5828260405161234e92919061459a565b6024612a71600267ffffffffffffffff6145c7565b612a7b91906145ed565b67ffffffffffffffff1681565b5f858152600860205260409020546001600160a01b03168115612b50576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303815f875af1158015612b2a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b4e9190614299565b505b6024612b65600267ffffffffffffffff6145c7565b612b6f91906145ed565b67ffffffffffffffff168611612c02576040517fb2267a7b00000000000000000000000000000000000000000000000000000000815285906001600160a01b0383169063b2267a7b903490612bce9085908a908a908a90600401614643565b5f604051808303818588803b158015612be5575f80fd5b505af1158015612bf7573d5f803e3d5ffd5b505050505050612c7e565b6040517f6585ecdc0000000000000000000000000000000000000000000000000000000081526001600160a01b03821690636585ecdc903490612c4f90899089908990899060040161467b565b5f604051808303818588803b158015612c66575f80fd5b505af1158015612c78573d5f803e3d5ffd5b50505050505b505050505050565b8251845114612cb557835183516040516308151c1160e41b815260048101929092526024820152604401610754565b8151845114612ce457835182516040516308151c1160e41b815260048101929092526024820152604401610754565b8051845114612d1357835181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f805f5b8651811015612f5a57868181518110612d3257612d326142b8565b60200260200101518310612d7657868181518110612d5257612d526142b8565b6020026020010151604051633881b68960e01b815260040161075491815260200190565b868181518110612d8857612d886142b8565b60200260200101519250858181518110612da457612da46142b8565b6020026020010151515f03612dcc57604051637c946ed760e01b815260040160405180910390fd5b838181518110612dde57612dde6142b8565b602002602001015182612df191906142cc565b91505f600154905080878381518110612e0c57612e0c6142b8565b6020026020010151511115612e5b57868281518110612e2d57612e2d6142b8565b60200260200101515181604051637ae5968560e01b8152600401610754929190918252602082015260400190565b5f805b888481518110612e7057612e706142b8565b602002602001015151811015612f4c57888481518110612e9257612e926142b8565b60200260200101518181518110612eab57612eab6142b8565b60200260200101515f1c825f1c10612f0c57888481518110612ecf57612ecf6142b8565b60200260200101518181518110612ee857612ee86142b8565b6020026020010151604051636aba776560e11b815260040161075491815260200190565b888481518110612f1e57612f1e6142b8565b60200260200101518181518110612f3757612f376142b8565b60200260200101519150806001019050612e5e565b505050806001019050612d17565b50803414612c7e5760405163312b003360e01b815234600482015260248101829052604401610754565b6040805160038082526080820190925260609182918291602082018380368337019050509250845167ffffffffffffffff811115612fc457612fc4613c4d565b604051908082528060200260200182016040528015612ff757816020015b6060815260200190600190039081612fe25790505b509150845167ffffffffffffffff81111561301457613014613c4d565b60405190808252806020026020018201604052801561303d578160200160208202803683370190505b5090505f5b85518110156134d4575f60085f888481518110613061576130616142b8565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f816001600160a01b031663a8b2ae026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130ec9190614255565b9050868381518110613100576131006142b8565b60200260200101515167ffffffffffffffff81111561312157613121613c4d565b60405190808252806020026020018201604052801561314a578160200160208202803683370190505b5085848151811061315d5761315d6142b8565b60200260200101819052505f5b87848151811061317c5761317c6142b8565b602002602001015151811015613363577f00000000000000000000000000000000000000000000000000000000000000008885815181106131bf576131bf6142b8565b602002602001015182815181106131d8576131d86142b8565b60200260200101510361322057604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5f805f8061327b8e8e8a8151811061323a5761323a6142b8565b60200260200101518e8b81518110613254576132546142b8565b6020026020010151888151811061326d5761326d6142b8565b602002602001015189611654565b5f8181526006602052604090208290558d519397509195509350915084908b908a9081106132ab576132ab6142b8565b602002602001015186815181106132c4576132c46142b8565b602002602001018181525050838989815181106132e3576132e36142b8565b602002602001018181516132f791906142cc565b9052508a5184908c905f9061330e5761330e6142b8565b6020026020010181815161332291906142cc565b9052508a5183908c90600290811061333c5761333c6142b8565b6020026020010181815161335091906142cc565b905250506001909301925061316a915050565b505f848481518110613377576133776142b8565b60200260200101511115613486575f60095f8a868151811061339b5761339b6142b8565b602002602001015181526020019081526020015f205490505f811115613484578484815181106133cd576133cd6142b8565b60200260200101518110613426578484815181106133ed576133ed6142b8565b6020026020010151816134009190614280565b90505f858581518110613415576134156142b8565b602002602001018181525050613454565b80858581518110613439576134396142b8565b6020026020010181815161344d9190614280565b9052505f90505b8060095f8b878151811061346a5761346a6142b8565b602002602001015181526020019081526020015f20819055505b505b838381518110613498576134986142b8565b6020026020010151866001815181106134b3576134b36142b8565b602002602001018181516134c791906142cc565b9052505050600101613042565b5093509350939050565b5f5b8651811015613ade575f60085f8984815181106134ff576134ff6142b8565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f84838151811061353c5761353c6142b8565b60200260200101511115613607577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb8286858151811061358c5761358c6142b8565b60200260200101516040518363ffffffff1660e01b81526004016135c59291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af11580156135e1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136059190614299565b505b5f8088848151811061361b5761361b6142b8565b60200260200101515167ffffffffffffffff81111561363c5761363c613c4d565b604051908082528060200260200182016040528015613665578160200160208202803683370190505b5090505f5b89858151811061367c5761367c6142b8565b6020026020010151518110156136fe575f89868151811061369f5761369f6142b8565b602002602001015182815181106136b8576136b86142b8565b602002602001015111156136f65760018282815181106136da576136da6142b8565b911515602092830291909101909101526136f383614699565b92505b60010161366a565b505f8267ffffffffffffffff81111561371957613719613c4d565b604051908082528060200260200182016040528015613742578160200160208202803683370190505b5090505f8367ffffffffffffffff81111561375f5761375f613c4d565b604051908082528060200260200182016040528015613788578160200160208202803683370190505b5090505f805b8c88815181106137a0576137a06142b8565b602002602001015151811015613884578481815181106137c2576137c26142b8565b60200260200101511561387c578c88815181106137e1576137e16142b8565b602002602001015181815181106137fa576137fa6142b8565b6020026020010151848381518110613814576138146142b8565b6020026020010181815250508b8881518110613832576138326142b8565b6020026020010151818151811061384b5761384b6142b8565b6020026020010151838381518110613865576138656142b8565b602090810291909101015261387982614699565b91505b60010161378e565b50602461389a600267ffffffffffffffff6145c7565b6138a491906145ed565b67ffffffffffffffff168d88815181106138c0576138c06142b8565b602002602001015111613a20575f835167ffffffffffffffff8111156138e8576138e8613c4d565b604051908082528060200260200182016040528015613911578160200160208202803683370190505b5090505f5b845181101561396d57848181518110613931576139316142b8565b60200260200101515f1c82828151811061394d5761394d6142b8565b6001600160a01b0390921660209283029190910190910152600101613916565b50866001600160a01b031663bde526618a8a8151811061398f5761398f6142b8565b602002602001015183868f8d815181106139ab576139ab6142b8565b60200260200101518f8e815181106139c5576139c56142b8565b60200260200101516040518663ffffffff1660e01b81526004016139ec94939291906146b1565b5f604051808303818588803b158015613a03575f80fd5b505af1158015613a15573d5f803e3d5ffd5b505050505050613acd565b856001600160a01b03166355442b59898981518110613a4157613a416142b8565b602002602001015185858e8c81518110613a5d57613a5d6142b8565b60200260200101518e8d81518110613a7757613a776142b8565b60200260200101516040518663ffffffff1660e01b8152600401613a9e94939291906146fb565b5f604051808303818588803b158015613ab5575f80fd5b505af1158015613ac7573d5f803e3d5ffd5b50505050505b5050505050508060010190506134e0565b50505050505050565b5f805f60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b3a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613b5e91906142df565b5f86815260066020526040812054945063ffffffff919091169150839003613b9957604051637c946ed760e01b815260040160405180910390fd5b808303613bce5782613bac600183614280565b604051637ae5968560e01b815260048101929092526024820152604401610754565b5f85815260076020526040902054600181118015613bec5750808410155b15613bfd5783613bac600183614280565b613c0785856142cc565b9250600181118015613c1857508083115b15613c21578092505b81831115613c2d578192505b50509250929050565b5f60208284031215613c46575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613c8a57613c8a613c4d565b604052919050565b5f82601f830112613ca1575f80fd5b813567ffffffffffffffff811115613cbb57613cbb613c4d565b613cce601f8201601f1916602001613c61565b818152846020838601011115613ce2575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215613d11575f80fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115613d3c575f80fd5b613d4887828801613c92565b91505092959194509250565b5f67ffffffffffffffff821115613d6d57613d6d613c4d565b5060051b60200190565b5f82601f830112613d86575f80fd5b81356020613d9b613d9683613d54565b613c61565b8083825260208201915060208460051b870101935086841115613dbc575f80fd5b602086015b84811015613dd85780358352918301918301613dc1565b509695505050505050565b5f82601f830112613df2575f80fd5b81356020613e02613d9683613d54565b82815260059290921b84018101918181019086841115613e20575f80fd5b8286015b84811015613dd857803567ffffffffffffffff811115613e42575f80fd5b613e508986838b0101613c92565b845250918301918301613e24565b5f805f805f60a08688031215613e72575f80fd5b8535945067ffffffffffffffff8060208801351115613e8f575f80fd5b613e9f8860208901358901613d77565b94508060408801351115613eb1575f80fd5b6040870135870188601f820112613ec6575f80fd5b613ed3613d968235613d54565b81358082526020808301929160051b8401018b1015613ef0575f80fd5b602083015b6020843560051b850101811015613f8a578481351115613f13575f80fd5b803584018c603f820112613f25575f80fd5b613f35613d966020830135613d54565b602082810135808352908201919060051b83016040018f811115613f57575f80fd5b6040840193505b80841015613f79578335835260209384019390920191613f5e565b508552505060209283019201613ef5565b50955050506060870135811015613f9f575f80fd5b613faf8860608901358901613de3565b92508060808801351115613fc1575f80fd5b50613fd28760808801358801613d77565b90509295509295909350565b5f805f60608486031215613ff0575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52602160045260245ffd5b602081016004831061403b57634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215614051575f80fd5b81356004811061405f575f80fd5b9392505050565b5f805f8060808587031215614079575f80fd5b5050823594602084013594506040840135936060013592509050565b80356001600160a01b03811681146140ab575f80fd5b919050565b5f602082840312156140c0575f80fd5b61405f82614095565b5f80604083850312156140da575f80fd5b50508035926020909101359150565b5f805f606084860312156140fb575f80fd5b61410484614095565b925061411260208501614095565b915061412060408501614095565b90509250925092565b5f806040838503121561413a575f80fd5b823567ffffffffffffffff80821115614151575f80fd5b61415d86838701613d77565b93506020850135915080821115614172575f80fd5b5061417f85828601613d77565b9150509250929050565b5f806040838503121561419a575f80fd5b823567ffffffffffffffff808211156141b1575f80fd5b818501915085601f8301126141c4575f80fd5b813560206141d4613d9683613d54565b82815260059290921b840181019181810190898411156141f2575f80fd5b948201945b838610156142175761420886614095565b825294820194908201906141f7565b96505086013592505080821115614172575f80fd5b805160ff811681146140ab575f80fd5b5f6020828403121561424c575f80fd5b61405f8261422c565b5f60208284031215614265575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156142935761429361426c565b92915050565b5f602082840312156142a9575f80fd5b8151801515811461405f575f80fd5b634e487b7160e01b5f52603260045260245ffd5b808201808211156142935761429361426c565b5f602082840312156142ef575f80fd5b815163ffffffff8116811461405f575f80fd5b80516bffffffffffffffffffffffff811681146140ab575f80fd5b5f6080828403121561432d575f80fd5b6040516080810181811067ffffffffffffffff8211171561435057614350613c4d565b60405261435c83614302565b815261436a60208401614302565b6020820152604083015161ffff81168114614383575f80fd5b60408201526143946060840161422c565b60608201529392505050565b5f80604083850312156143b1575f80fd5b505080516020909101519092909150565b80820281158282048414176142935761429361426c565b634e487b7160e01b5f52601260045260245ffd5b5f826143fb576143fb6143d9565b500490565b600181815b8085111561443a57815f19048211156144205761442061426c565b8085161561442d57918102915b93841c9390800290614405565b509250929050565b5f8261445057506001614293565b8161445c57505f614293565b8160018114614472576002811461447c57614498565b6001915050614293565b60ff84111561448d5761448d61426c565b50506001821b614293565b5060208310610133831016604e8410600b84101617156144bb575081810a614293565b6144c58383614400565b805f19048211156144d8576144d861426c565b029392505050565b5f61405f8383614442565b5f815180845260208085019450602084015f5b8381101561451a578151875295820195908201906001016144fe565b509495945050505050565b6001600160a01b0384168152606060208201525f61454660608301856144eb565b828103604084015261455881856144eb565b9695505050505050565b5f815180845260208085019450602084015f5b8381101561451a5781516001600160a01b031687529582019590820190600101614575565b604081525f6145ac6040830185614562565b82810360208401526145be81856144eb565b95945050505050565b5f67ffffffffffffffff808416806145e1576145e16143d9565b92169190910492915050565b67ffffffffffffffff82811682821603908082111561460e5761460e61426c565b5092915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152836020820152608060408201525f61466a6080830185614615565b905082606083015295945050505050565b848152836020820152608060408201525f61466a6080830185614615565b5f600182016146aa576146aa61426c565b5060010190565b608081525f6146c36080830187614562565b82810360208401526146d581876144eb565b905082810360408401526146e98186614615565b91505082606083015295945050505050565b608080825285519082018190525f9060209060a0840190828901845b8281101561473357815184529284019290840190600101614717565b505050838103602085015261474881886144eb565b91505082810360408401526146e9818661461556fea2646970667358221220d5ad21b1e3c7f46f079be5de02f8abed25c59cb8c181f76db5750438335cf60864736f6c63430008190033",
- "deployedBytecode": "0x6080604052600436106101da575f3560e01c806379bc81dd116100fd578063bc7d5c5c11610092578063dcb5ccc411610062578063dcb5ccc4146105f9578063e09177781461062d578063e6be59e714610660578063f4da12ba14610693575f80fd5b8063bc7d5c5c14610568578063d529779314610587578063d7accbcc146105a6578063d8bf69bf146105da575f80fd5b80639649a35c116100cd5780639649a35c146104eb578063a5edd4fc146104ff578063a6f9dae11461051e578063bb78678f1461053d575f80fd5b806379bc81dd1461046e5780638513e77d1461048d5780638833c205146104b85780638da5cb5b146104cc575f80fd5b80633c18d1dd1161017357806361d027b31161014357806361d027b3146103d257806363096509146103f157806363c4d28e14610410578063777e49c91461042f575f80fd5b80633c18d1dd146103345780634ac7251d146103675780635a55a482146103865780635c975abb146103a5575f80fd5b80632ad923dc116101ae5780632ad923dc146102cc5780632c0f3f29146102f757806334be5af41461030c5780633907196c14610321575f80fd5b806231d115146101de5780630d17db111461022e5780630d3241ee1461026c5780632a3bb6931461028b575b5f80fd5b3480156101e9575f80fd5b506102117f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610239575f80fd5b5061025c610248366004613c36565b600a6020525f908152604090205460ff1681565b6040519015158152602001610225565b348015610277575f80fd5b50600554610211906001600160a01b031681565b348015610296575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610225565b3480156102d7575f80fd5b506102be6102e6366004613c36565b60066020525f908152604090205481565b61030a610305366004613cfe565b6106a7565b005b348015610317575f80fd5b506102be60015481565b61030a61032f366004613e5e565b610be6565b34801561033f575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b348015610372575f80fd5b50600354610211906001600160a01b031681565b348015610391575f80fd5b5061030a6103a0366004613fde565b611148565b3480156103b0575f80fd5b506002546103c590600160a81b900460ff1681565b604051610225919061401b565b3480156103dd575f80fd5b50600454610211906001600160a01b031681565b3480156103fc575f80fd5b5061030a61040b366004614041565b611312565b34801561041b575f80fd5b5061030a61042a366004613c36565b6113d1565b34801561043a575f80fd5b5061044e610449366004614066565b611654565b604080519485526020850193909352918301526060820152608001610225565b348015610479575f80fd5b5061030a610488366004613fde565b611b99565b348015610498575f80fd5b506102be6104a7366004613c36565b60076020525f908152604090205481565b3480156104c3575f80fd5b506102be5f5481565b3480156104d7575f80fd5b50600254610211906001600160a01b031681565b3480156104f6575f80fd5b5061030a611ca8565b34801561050a575f80fd5b5061030a610519366004613c36565b61204a565b348015610529575f80fd5b5061030a6105383660046140b0565b6121ed565b348015610548575f80fd5b506102be610557366004613c36565b60096020525f908152604090205481565b348015610573575f80fd5b5061030a6105823660046140c9565b6122aa565b348015610592575f80fd5b5061030a6105a13660046140e9565b61235a565b3480156105b1575f80fd5b506105c56105c0366004614129565b6124c8565b60408051928352602083019190915201610225565b3480156105e5575f80fd5b5061030a6105f4366004614189565b6128f9565b348015610604575f80fd5b50610211610613366004613c36565b60086020525f90815260409020546001600160a01b031681565b348015610638575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066b575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561069e575f80fd5b506102be612a5c565b6002546001600160a01b90910460ff1611156106d6576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f83900361070a57604051637c946ed760e01b815260040160405180910390fd5b5f82900361072b5760405163d92e233d60e01b815260040160405180910390fd5b5f548085111561075d57604051637ae5968560e01b815260048101869052602481018290526044015b60405180910390fd5b60028054600160a81b900460ff169081600381111561077e5761077e614007565b148061079b5750600381600381111561079957610799614007565b145b8061081257506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156107e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061080b919061423c565b60ff166002145b15610830576040516313d0ff5960e31b815260040160405180910390fd5b5f8581526008602090815260408083205481517fa8b2ae0200000000000000000000000000000000000000000000000000000000815291516001600160a01b039091169392849263a8b2ae0292600480830193928290030181865afa15801561089b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bf9190614255565b90505f805f806108d18c8c8c88611654565b5f81815260066020526040902082905592965090945092509050821561094b57600354604051635e148f0960e11b8152600481018590526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015610934575f80fd5b505af1158015610946573d5f803e3d5ffd5b505050505b5f8415610b8157505f8b815260096020526040902054849080156109a5578181106109845761097a8282614280565b90505f9150610994565b61098e8183614280565b91505f90505b5f8d81526009602052604090208190555b8115610b72576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610a0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a339190614255565b60048054604051637ff796ab60e01b815230928101929092525f6024830152604482018690529192506001600160a01b0390911690637ff796ab906064016020604051808303815f875af1158015610a8d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab19190614299565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610b16573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3a9190614255565b610b449190614280565b9050828114610b705760405163312b003360e01b81526004810182905260248101849052604401610754565b505b610b7f8d8d888e86612a88565b505b604080518681526020810183905290810185905233907f02b21954a7bf2d6a171db9a87b430a3723605c554db00adcb95b26ce8464f2809060600160405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050505050565b6002546001600160a01b90910460ff161115610c15576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179055610c3484848484612c86565b5f5480861115610c6157604051637ae5968560e01b81526004810187905260248101829052604401610754565b60028054600160a81b900460ff1690816003811115610c8257610c82614007565b1480610c9f57506003816003811115610c9d57610c9d614007565b145b80610d1657506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015610ceb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d0f919061423c565b60ff166002145b15610d34576040516313d0ff5960e31b815260040160405180910390fd5b6060806060610d448a8a8a612f84565b825192955090935091505f9084906002908110610d6357610d636142b8565b60200260200101511115610def5760035483516001600160a01b039091169063bc291e129085906002908110610d9b57610d9b6142b8565b60200260200101516040518263ffffffff1660e01b8152600401610dc191815260200190565b5f604051808303815f87803b158015610dd8575f80fd5b505af1158015610dea573d5f803e3d5ffd5b505050505b5f835f81518110610e0257610e026142b8565b60200260200101511115611086575f83600181518110610e2457610e246142b8565b60200260200101511115611078576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610e96573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eba9190614255565b60045485519192506001600160a01b031690637ff796ab9030905f9088906001908110610ee957610ee96142b8565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303815f875af1158015610f5c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f809190614299565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610fe5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110099190614255565b6110139190614280565b905083600181518110611028576110286142b8565b6020026020010151811461107657808460018151811061104a5761104a6142b8565b602002602001015160405163312b003360e01b8152600401610754929190918252602082015260400190565b505b6110868989848a858b6134de565b336001600160a01b03167f02b21954a7bf2d6a171db9a87b430a3723605c554db00adcb95b26ce8464f280845f815181106110c3576110c36142b8565b6020026020010151856001815181106110de576110de6142b8565b6020026020010151866002815181106110f9576110f96142b8565b6020026020010151604051611121939291909283526020830191909152604082015260600190565b60405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050565b6002546001600160a01b031633146111885760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b821580611193575081155b8061119c575080155b156111ba57604051637c946ed760e01b815260040160405180910390fd5b4683036111dd57604051633881b68960e01b815260048101849052602401610754565b5f838152600960205260408120546111f69084906142cc565b90506bffffffffffffffffffffffff81111561123a57604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f8481526009602090815260408083208490556008909152908190205490517fac65ded2000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690819063ac65ded2906024015f604051808303815f87803b1580156112b1575f80fd5b505af11580156112c3573d5f803e3d5ffd5b505060408051888152602081018890529081018590528592507f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97591506060015b60405180910390a25050505050565b6002546001600160a01b031633146113525760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b600280548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16600160a81b83600381111561139257611392614007565b02179055507fa814f27828c0243d429ea8c7033cb10f0c825b9466fdc04f63e0cca26c28eb8a816040516113c6919061401b565b60405180910390a150565b6005546001600160a01b031633146114115760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b807f00000000000000000000000000000000000000000000000000000000000000000361147357604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b600354604080517f14b19c5a00000000000000000000000000000000000000000000000000000000815290515f926001600160a01b0316916314b19c5a9160048083019260209291908290030181865afa1580156114d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114f791906142df565b60035463ffffffff9190911691505f906001600160a01b031663d4ee9f8d611520600185614280565b6040518263ffffffff1660e01b815260040161153e91815260200190565b602060405180830381865afa158015611559573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061157d9190614255565b90505f60035f9054906101000a90046001600160a01b03166001600160a01b031663d2b3996f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f491906142df565b63ffffffff1690505f62093a8061160b83856142cc565b6116159190614280565b905080421061164057604051637ae5968560e01b815242600482015260248101829052604401610754565b5050505f9182526007602052604090912055565b5f805f80865f0361167857604051637c946ed760e01b815260040160405180910390fd5b5f8690036116995760405163d92e233d60e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000086036116fb57604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5060408051808201825286815260209081018881528251808301899052905181840152825180820384018152606090910190925281519101205f61173f828a613ae7565b6005546040516317d5e89d60e31b8152600481018b9052602481018c90529195509192506001600160a01b039091169063beaf44e8906044015f604051808303815f87803b15801561178f575f80fd5b505af11580156117a1573d5f803e3d5ffd5b5083925050505b83811015611b8c575f818152600a602052604090205460ff16611b8457600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa15801561180c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611830919061431d565b606081015190915060ff16156118cf57604081015161ffff16158015611866575060208101516bffffffffffffffffffffffff16155b156118ca5761ffff7f00000000000000000000000000000000000000000000000000000000000000001660408201526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660208201525b6118d5565b50611b84565b60035460405163d4ee9f8d60e01b8152600481018490525f916001600160a01b03169063d4ee9f8d90602401602060405180830381865afa15801561191c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119409190614255565b600554604051630c88d47f60e41b8152600481018d9052602481018e9052604481018390529192505f9182916001600160a01b03169063c88d47f0906064016040805180830381865afa158015611999573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119bd91906143a0565b91509150805f03611a05575f858152600a60205260409020805460ff1916600117905583516119fa906bffffffffffffffffffffffff168a6142cc565b985050505050611b84565b83515f9081906bffffffffffffffffffffffff168184821115611a3257611a2c8583614280565b90508491505b6040880151611a4b9061ffff16655af3107a40006143c2565b861015611a8157670de0b6b3a764000086611a6684846142cc565b611a7091906143c2565b611a7a91906143ed565b9250611b6f565b670de0b6b3a7640000611a9487846143c2565b611a9e91906143ed565b9350670de0b6b3a7640000611ab387836143c2565b611abd91906143ed565b925087602001516bffffffffffffffffffffffff16915081841115611af657611ae68285614280565b611af090846142cc565b92508193505b60128f1015611b62575f8f6012611b0d9190614280565b611b1890600a6144e0565b611b2290866143ed565b90508f6012611b319190614280565b611b3c90600a6144e0565b611b4690826143c2565b9050611b528186614280565b611b5c90856142cc565b90945092505b611b6c848f6142cc565b9d505b611b79838e6142cc565b9c5050505050505050505b6001016117a8565b5050945094509450949050565b5f838152600860205260409020546001600160a01b0316338114611bfa576040517fdeeeedec0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0382166024820152604401610754565b5f84815260096020526040812054611c139085906142cc565b90506bffffffffffffffffffffffff811115611c5757604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f85815260096020908152604091829020839055815187815290810186905290810182905283907f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97590606001611303565b6002546001600160a01b90910460ff161115611cd7576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f80548190611d1a907f000000000000000000000000000000000000000000000000000000000000000090613ae7565b6005546040516317d5e89d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201529294509092506001600160a01b03169063beaf44e8906044015f604051808303815f87803b158015611d86575f80fd5b505af1158015611d98573d5f803e3d5ffd5b50507f00000000000000000000000000000000000000000000000000000000000000005f90815260066020526040812084905591508390505b82811015611f8857600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611e20573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e44919061431d565b60035460405163d4ee9f8d60e01b8152600481018590529192505f916001600160a01b039091169063d4ee9f8d90602401602060405180830381865afa158015611e90573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eb49190614255565b600554604051630c88d47f60e41b81527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604481018390529192505f916001600160a01b039091169063c88d47f0906064016040805180830381865afa158015611f2b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f4f91906143a0565b508351909150611f6e9082906bffffffffffffffffffffffff166143c2565b611f7890866142cc565b9450505050806001019050611dd1565b50611f9b670de0b6b3a7640000826143ed565b90508015611ffd57600354604051635e148f0960e11b8152600481018390526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015611fe6575f80fd5b505af1158015611ff8573d5f803e3d5ffd5b505050505b60405181815233907f2a8de497d698d6869cb0844411788378e76214d03a541eec6ba514b795d9f42e9060200160405180910390a250506002805460ff60a01b1916600160a01b17905550565b6005546001600160a01b0316331461208a5760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b60028054600160a81b900460ff16908160038111156120ab576120ab614007565b14806120c8575060038160038111156120c6576120c6614007565b145b8061213f57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015612114573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612138919061423c565b60ff166002145b1561215d576040516313d0ff5960e31b815260040160405180910390fd5b60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121d191906142df565b5f9283526006602052604090922063ffffffff90921690915550565b6002546001600160a01b0316331461222d5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b0381166122545760405163d92e233d60e01b815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b905f90a250565b6002546001600160a01b031633146122ea5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b8115806122f5575080155b1561231357604051637c946ed760e01b815260040160405180910390fd5b5f829055600181905560408051838152602081018390527f61f6c4cc9665a257352c0b46189ffc2ae6fbbc11e155ff20901217ff203a517e91015b60405180910390a15050565b6002546001600160a01b0316331461239a5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b038316156123fd576003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385169081179091556040517f4672fe7e13cfb163442d0b729b5733fb3efafc66cbe3677eac9940eb41c284c2905f90a25b6001600160a01b03821615612460576004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040517f7dae230f18360d76a040c81f050aa14eb9d6dc7901b20fc5d855e2a20fe814d1905f90a25b6001600160a01b038116156124c3576005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f04a606379838ed6fc83fd189eea9d1835b5eff05035c4b74622911ea2ae6b217905f90a25b505050565b5f806001600260149054906101000a900460ff1660ff1611156124fe576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179081905560ff600160a81b90910416600181600381111561253257612532614007565b148061254f5750600381600381111561254d5761254d614007565b145b806125c657506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af115801561259b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125bf919061423c565b60ff166002145b156125e4576040516313d0ff5960e31b815260040160405180910390fd5b6003546040517f2e070f540000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632e070f549061263190339089908990600401614525565b60408051808303815f875af115801561264c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061267091906143a0565b90935091505f8061268184866142cc565b1115612859575f8315612717576040516370a0823160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156126f0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127149190614255565b90505b60048054604051637ff796ab60e01b8152339281019290925260248201879052604482018690526001600160a01b031690637ff796ab906064016020604051808303815f875af115801561276d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127919190614299565b91508315612857576040516370a0823160e01b815233600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156127fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128219190614255565b61282b9190614280565b90508381146128575760405163312b003360e01b81526004810182905260248101859052604401610754565b505b806128a0576040517f942dc9da0000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606401610754565b604080518581526020810185905233917f928890dff971de1394b7440848938a868d83445d2f7fb4b07938ae626c7cb130910160405180910390a250506002805460ff60a01b1916600160a01b17905590939092509050565b6002546001600160a01b031633146129395760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b8151158061294957508051825114155b1561297457815181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f5b8151811015612a2a57818181518110612991576129916142b8565b60200260200101515f036129b857604051637c946ed760e01b815260040160405180910390fd5b8281815181106129ca576129ca6142b8565b602002602001015160085f8484815181106129e7576129e76142b8565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001019050612976565b507fe87460f6c400fa0166984512586d7bdf03a3230bbadf9651f27f08716dd77fa5828260405161234e92919061459a565b6024612a71600267ffffffffffffffff6145c7565b612a7b91906145ed565b67ffffffffffffffff1681565b5f858152600860205260409020546001600160a01b03168115612b50576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303815f875af1158015612b2a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b4e9190614299565b505b6024612b65600267ffffffffffffffff6145c7565b612b6f91906145ed565b67ffffffffffffffff168611612c02576040517fb2267a7b00000000000000000000000000000000000000000000000000000000815285906001600160a01b0383169063b2267a7b903490612bce9085908a908a908a90600401614643565b5f604051808303818588803b158015612be5575f80fd5b505af1158015612bf7573d5f803e3d5ffd5b505050505050612c7e565b6040517f6585ecdc0000000000000000000000000000000000000000000000000000000081526001600160a01b03821690636585ecdc903490612c4f90899089908990899060040161467b565b5f604051808303818588803b158015612c66575f80fd5b505af1158015612c78573d5f803e3d5ffd5b50505050505b505050505050565b8251845114612cb557835183516040516308151c1160e41b815260048101929092526024820152604401610754565b8151845114612ce457835182516040516308151c1160e41b815260048101929092526024820152604401610754565b8051845114612d1357835181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f805f5b8651811015612f5a57868181518110612d3257612d326142b8565b60200260200101518310612d7657868181518110612d5257612d526142b8565b6020026020010151604051633881b68960e01b815260040161075491815260200190565b868181518110612d8857612d886142b8565b60200260200101519250858181518110612da457612da46142b8565b6020026020010151515f03612dcc57604051637c946ed760e01b815260040160405180910390fd5b838181518110612dde57612dde6142b8565b602002602001015182612df191906142cc565b91505f600154905080878381518110612e0c57612e0c6142b8565b6020026020010151511115612e5b57868281518110612e2d57612e2d6142b8565b60200260200101515181604051637ae5968560e01b8152600401610754929190918252602082015260400190565b5f805b888481518110612e7057612e706142b8565b602002602001015151811015612f4c57888481518110612e9257612e926142b8565b60200260200101518181518110612eab57612eab6142b8565b60200260200101515f1c825f1c10612f0c57888481518110612ecf57612ecf6142b8565b60200260200101518181518110612ee857612ee86142b8565b6020026020010151604051636aba776560e11b815260040161075491815260200190565b888481518110612f1e57612f1e6142b8565b60200260200101518181518110612f3757612f376142b8565b60200260200101519150806001019050612e5e565b505050806001019050612d17565b50803414612c7e5760405163312b003360e01b815234600482015260248101829052604401610754565b6040805160038082526080820190925260609182918291602082018380368337019050509250845167ffffffffffffffff811115612fc457612fc4613c4d565b604051908082528060200260200182016040528015612ff757816020015b6060815260200190600190039081612fe25790505b509150845167ffffffffffffffff81111561301457613014613c4d565b60405190808252806020026020018201604052801561303d578160200160208202803683370190505b5090505f5b85518110156134d4575f60085f888481518110613061576130616142b8565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f816001600160a01b031663a8b2ae026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130ec9190614255565b9050868381518110613100576131006142b8565b60200260200101515167ffffffffffffffff81111561312157613121613c4d565b60405190808252806020026020018201604052801561314a578160200160208202803683370190505b5085848151811061315d5761315d6142b8565b60200260200101819052505f5b87848151811061317c5761317c6142b8565b602002602001015151811015613363577f00000000000000000000000000000000000000000000000000000000000000008885815181106131bf576131bf6142b8565b602002602001015182815181106131d8576131d86142b8565b60200260200101510361322057604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5f805f8061327b8e8e8a8151811061323a5761323a6142b8565b60200260200101518e8b81518110613254576132546142b8565b6020026020010151888151811061326d5761326d6142b8565b602002602001015189611654565b5f8181526006602052604090208290558d519397509195509350915084908b908a9081106132ab576132ab6142b8565b602002602001015186815181106132c4576132c46142b8565b602002602001018181525050838989815181106132e3576132e36142b8565b602002602001018181516132f791906142cc565b9052508a5184908c905f9061330e5761330e6142b8565b6020026020010181815161332291906142cc565b9052508a5183908c90600290811061333c5761333c6142b8565b6020026020010181815161335091906142cc565b905250506001909301925061316a915050565b505f848481518110613377576133776142b8565b60200260200101511115613486575f60095f8a868151811061339b5761339b6142b8565b602002602001015181526020019081526020015f205490505f811115613484578484815181106133cd576133cd6142b8565b60200260200101518110613426578484815181106133ed576133ed6142b8565b6020026020010151816134009190614280565b90505f858581518110613415576134156142b8565b602002602001018181525050613454565b80858581518110613439576134396142b8565b6020026020010181815161344d9190614280565b9052505f90505b8060095f8b878151811061346a5761346a6142b8565b602002602001015181526020019081526020015f20819055505b505b838381518110613498576134986142b8565b6020026020010151866001815181106134b3576134b36142b8565b602002602001018181516134c791906142cc565b9052505050600101613042565b5093509350939050565b5f5b8651811015613ade575f60085f8984815181106134ff576134ff6142b8565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f84838151811061353c5761353c6142b8565b60200260200101511115613607577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb8286858151811061358c5761358c6142b8565b60200260200101516040518363ffffffff1660e01b81526004016135c59291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af11580156135e1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136059190614299565b505b5f8088848151811061361b5761361b6142b8565b60200260200101515167ffffffffffffffff81111561363c5761363c613c4d565b604051908082528060200260200182016040528015613665578160200160208202803683370190505b5090505f5b89858151811061367c5761367c6142b8565b6020026020010151518110156136fe575f89868151811061369f5761369f6142b8565b602002602001015182815181106136b8576136b86142b8565b602002602001015111156136f65760018282815181106136da576136da6142b8565b911515602092830291909101909101526136f383614699565b92505b60010161366a565b505f8267ffffffffffffffff81111561371957613719613c4d565b604051908082528060200260200182016040528015613742578160200160208202803683370190505b5090505f8367ffffffffffffffff81111561375f5761375f613c4d565b604051908082528060200260200182016040528015613788578160200160208202803683370190505b5090505f805b8c88815181106137a0576137a06142b8565b602002602001015151811015613884578481815181106137c2576137c26142b8565b60200260200101511561387c578c88815181106137e1576137e16142b8565b602002602001015181815181106137fa576137fa6142b8565b6020026020010151848381518110613814576138146142b8565b6020026020010181815250508b8881518110613832576138326142b8565b6020026020010151818151811061384b5761384b6142b8565b6020026020010151838381518110613865576138656142b8565b602090810291909101015261387982614699565b91505b60010161378e565b50602461389a600267ffffffffffffffff6145c7565b6138a491906145ed565b67ffffffffffffffff168d88815181106138c0576138c06142b8565b602002602001015111613a20575f835167ffffffffffffffff8111156138e8576138e8613c4d565b604051908082528060200260200182016040528015613911578160200160208202803683370190505b5090505f5b845181101561396d57848181518110613931576139316142b8565b60200260200101515f1c82828151811061394d5761394d6142b8565b6001600160a01b0390921660209283029190910190910152600101613916565b50866001600160a01b031663bde526618a8a8151811061398f5761398f6142b8565b602002602001015183868f8d815181106139ab576139ab6142b8565b60200260200101518f8e815181106139c5576139c56142b8565b60200260200101516040518663ffffffff1660e01b81526004016139ec94939291906146b1565b5f604051808303818588803b158015613a03575f80fd5b505af1158015613a15573d5f803e3d5ffd5b505050505050613acd565b856001600160a01b03166355442b59898981518110613a4157613a416142b8565b602002602001015185858e8c81518110613a5d57613a5d6142b8565b60200260200101518e8d81518110613a7757613a776142b8565b60200260200101516040518663ffffffff1660e01b8152600401613a9e94939291906146fb565b5f604051808303818588803b158015613ab5575f80fd5b505af1158015613ac7573d5f803e3d5ffd5b50505050505b5050505050508060010190506134e0565b50505050505050565b5f805f60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b3a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613b5e91906142df565b5f86815260066020526040812054945063ffffffff919091169150839003613b9957604051637c946ed760e01b815260040160405180910390fd5b808303613bce5782613bac600183614280565b604051637ae5968560e01b815260048101929092526024820152604401610754565b5f85815260076020526040902054600181118015613bec5750808410155b15613bfd5783613bac600183614280565b613c0785856142cc565b9250600181118015613c1857508083115b15613c21578092505b81831115613c2d578192505b50509250929050565b5f60208284031215613c46575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613c8a57613c8a613c4d565b604052919050565b5f82601f830112613ca1575f80fd5b813567ffffffffffffffff811115613cbb57613cbb613c4d565b613cce601f8201601f1916602001613c61565b818152846020838601011115613ce2575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215613d11575f80fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115613d3c575f80fd5b613d4887828801613c92565b91505092959194509250565b5f67ffffffffffffffff821115613d6d57613d6d613c4d565b5060051b60200190565b5f82601f830112613d86575f80fd5b81356020613d9b613d9683613d54565b613c61565b8083825260208201915060208460051b870101935086841115613dbc575f80fd5b602086015b84811015613dd85780358352918301918301613dc1565b509695505050505050565b5f82601f830112613df2575f80fd5b81356020613e02613d9683613d54565b82815260059290921b84018101918181019086841115613e20575f80fd5b8286015b84811015613dd857803567ffffffffffffffff811115613e42575f80fd5b613e508986838b0101613c92565b845250918301918301613e24565b5f805f805f60a08688031215613e72575f80fd5b8535945067ffffffffffffffff8060208801351115613e8f575f80fd5b613e9f8860208901358901613d77565b94508060408801351115613eb1575f80fd5b6040870135870188601f820112613ec6575f80fd5b613ed3613d968235613d54565b81358082526020808301929160051b8401018b1015613ef0575f80fd5b602083015b6020843560051b850101811015613f8a578481351115613f13575f80fd5b803584018c603f820112613f25575f80fd5b613f35613d966020830135613d54565b602082810135808352908201919060051b83016040018f811115613f57575f80fd5b6040840193505b80841015613f79578335835260209384019390920191613f5e565b508552505060209283019201613ef5565b50955050506060870135811015613f9f575f80fd5b613faf8860608901358901613de3565b92508060808801351115613fc1575f80fd5b50613fd28760808801358801613d77565b90509295509295909350565b5f805f60608486031215613ff0575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52602160045260245ffd5b602081016004831061403b57634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215614051575f80fd5b81356004811061405f575f80fd5b9392505050565b5f805f8060808587031215614079575f80fd5b5050823594602084013594506040840135936060013592509050565b80356001600160a01b03811681146140ab575f80fd5b919050565b5f602082840312156140c0575f80fd5b61405f82614095565b5f80604083850312156140da575f80fd5b50508035926020909101359150565b5f805f606084860312156140fb575f80fd5b61410484614095565b925061411260208501614095565b915061412060408501614095565b90509250925092565b5f806040838503121561413a575f80fd5b823567ffffffffffffffff80821115614151575f80fd5b61415d86838701613d77565b93506020850135915080821115614172575f80fd5b5061417f85828601613d77565b9150509250929050565b5f806040838503121561419a575f80fd5b823567ffffffffffffffff808211156141b1575f80fd5b818501915085601f8301126141c4575f80fd5b813560206141d4613d9683613d54565b82815260059290921b840181019181810190898411156141f2575f80fd5b948201945b838610156142175761420886614095565b825294820194908201906141f7565b96505086013592505080821115614172575f80fd5b805160ff811681146140ab575f80fd5b5f6020828403121561424c575f80fd5b61405f8261422c565b5f60208284031215614265575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156142935761429361426c565b92915050565b5f602082840312156142a9575f80fd5b8151801515811461405f575f80fd5b634e487b7160e01b5f52603260045260245ffd5b808201808211156142935761429361426c565b5f602082840312156142ef575f80fd5b815163ffffffff8116811461405f575f80fd5b80516bffffffffffffffffffffffff811681146140ab575f80fd5b5f6080828403121561432d575f80fd5b6040516080810181811067ffffffffffffffff8211171561435057614350613c4d565b60405261435c83614302565b815261436a60208401614302565b6020820152604083015161ffff81168114614383575f80fd5b60408201526143946060840161422c565b60608201529392505050565b5f80604083850312156143b1575f80fd5b505080516020909101519092909150565b80820281158282048414176142935761429361426c565b634e487b7160e01b5f52601260045260245ffd5b5f826143fb576143fb6143d9565b500490565b600181815b8085111561443a57815f19048211156144205761442061426c565b8085161561442d57918102915b93841c9390800290614405565b509250929050565b5f8261445057506001614293565b8161445c57505f614293565b8160018114614472576002811461447c57614498565b6001915050614293565b60ff84111561448d5761448d61426c565b50506001821b614293565b5060208310610133831016604e8410600b84101617156144bb575081810a614293565b6144c58383614400565b805f19048211156144d8576144d861426c565b029392505050565b5f61405f8383614442565b5f815180845260208085019450602084015f5b8381101561451a578151875295820195908201906001016144fe565b509495945050505050565b6001600160a01b0384168152606060208201525f61454660608301856144eb565b828103604084015261455881856144eb565b9695505050505050565b5f815180845260208085019450602084015f5b8381101561451a5781516001600160a01b031687529582019590820190600101614575565b604081525f6145ac6040830185614562565b82810360208401526145be81856144eb565b95945050505050565b5f67ffffffffffffffff808416806145e1576145e16143d9565b92169190910492915050565b67ffffffffffffffff82811682821603908082111561460e5761460e61426c565b5092915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152836020820152608060408201525f61466a6080830185614615565b905082606083015295945050505050565b848152836020820152608060408201525f61466a6080830185614615565b5f600182016146aa576146aa61426c565b5060010190565b608081525f6146c36080830187614562565b82810360208401526146d581876144eb565b905082810360408401526146e98186614615565b91505082606083015295945050505050565b608080825285519082018190525f9060209060a0840190828901845b8281101561473357815184529284019290840190600101614717565b505050838103602085015261474881886144eb565b91505082810360408401526146e9818661461556fea2646970667358221220d5ad21b1e3c7f46f079be5de02f8abed25c59cb8c181f76db5750438335cf60864736f6c63430008190033",
+ "bytecode": "0x610120604052348015610010575f80fd5b50604051614c6a380380614c6a83398101604081905261002f91610226565b6002805460ff60a01b1933166001600160a81b031990911617600160a01b1760ff60a81b1916600160a91b1790556001600160a01b038916158061007a57506001600160a01b038816155b8061008c57506001600160a01b038716155b8061009e57506001600160a01b038616155b806100a7575084155b156100c55760405163d92e233d60e01b815260040160405180910390fd5b8315806100d0575082155b806100d9575081155b806100e2575080155b1561010057604051637c946ed760e01b815260040160405180910390fd5b61ffff82111561013357604051637ae5968560e01b81526004810183905261ffff60248201526044015b60405180910390fd5b6001600160601b0381111561016b57604051637ae5968560e01b8152600481018290526001600160601b03602482015260440161012a565b6001600160a01b0398891660c05260038054988a166001600160a01b0319998a1617905560048054978a16978916979097179096556005805495909816949096169390931790955560e0819052604080518082018252828152466020918201908152825180830194909452518383015281518084038301815260609093019091528151910120610100525f9390935560019290925560805260a0526102a5565b80516001600160a01b0381168114610221575f80fd5b919050565b5f805f805f805f805f6101208a8c03121561023f575f80fd5b6102488a61020b565b985061025660208b0161020b565b975061026460408b0161020b565b965061027260608b0161020b565b955060808a0151945060a08a0151935060c08a0151925060e08a015191506101008a015190509295985092959850929598565b60805160a05160c05160e051610100516148fc61036e5f395f81816103450152818161141701528181611d220152611dc901525f81816106710152818161144a015281816116c8015281816116fc01528181611d5901528181611ef3015281816131f0015261325601525f81816101ef015281816109c201528181610ac901528181610e5701528181610fa6015281816126f90152818161280601528181612b4601526135ae01525f818161063e01526118d101525f818161029c015261189d01526148fc5ff3fe6080604052600436106101da575f3560e01c806379bc81dd116100fd578063bc7d5c5c11610092578063dcb5ccc411610062578063dcb5ccc4146105f9578063e09177781461062d578063e6be59e714610660578063f4da12ba14610693575f80fd5b8063bc7d5c5c14610568578063d529779314610587578063d7accbcc146105a6578063d8bf69bf146105da575f80fd5b80639649a35c116100cd5780639649a35c146104eb578063a5edd4fc146104ff578063a6f9dae11461051e578063bb78678f1461053d575f80fd5b806379bc81dd1461046e5780638513e77d1461048d5780638833c205146104b85780638da5cb5b146104cc575f80fd5b80633c18d1dd1161017357806361d027b31161014357806361d027b3146103d257806363096509146103f157806363c4d28e14610410578063777e49c91461042f575f80fd5b80633c18d1dd146103345780634ac7251d146103675780635a55a482146103865780635c975abb146103a5575f80fd5b80632ad923dc116101ae5780632ad923dc146102cc5780632c0f3f29146102f757806334be5af41461030c5780633907196c14610321575f80fd5b806231d115146101de5780630d17db111461022e5780630d3241ee1461026c5780632a3bb6931461028b575b5f80fd5b3480156101e9575f80fd5b506102117f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610239575f80fd5b5061025c610248366004613ca3565b600a6020525f908152604090205460ff1681565b6040519015158152602001610225565b348015610277575f80fd5b50600554610211906001600160a01b031681565b348015610296575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610225565b3480156102d7575f80fd5b506102be6102e6366004613ca3565b60066020525f908152604090205481565b61030a610305366004613d6b565b6106a7565b005b348015610317575f80fd5b506102be60015481565b61030a61032f366004613ecb565b610bf4565b34801561033f575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b348015610372575f80fd5b50600354610211906001600160a01b031681565b348015610391575f80fd5b5061030a6103a036600461404b565b61114b565b3480156103b0575f80fd5b506002546103c590600160a81b900460ff1681565b6040516102259190614088565b3480156103dd575f80fd5b50600454610211906001600160a01b031681565b3480156103fc575f80fd5b5061030a61040b3660046140ae565b611315565b34801561041b575f80fd5b5061030a61042a366004613ca3565b6113d4565b34801561043a575f80fd5b5061044e6104493660046140d3565b611681565b604080519485526020850193909352918301526060820152608001610225565b348015610479575f80fd5b5061030a61048836600461404b565b611bc6565b348015610498575f80fd5b506102be6104a7366004613ca3565b60076020525f908152604090205481565b3480156104c3575f80fd5b506102be5f5481565b3480156104d7575f80fd5b50600254610211906001600160a01b031681565b3480156104f6575f80fd5b5061030a611cd5565b34801561050a575f80fd5b5061030a610519366004613ca3565b612077565b348015610529575f80fd5b5061030a61053836600461411d565b612243565b348015610548575f80fd5b506102be610557366004613ca3565b60096020525f908152604090205481565b348015610573575f80fd5b5061030a610582366004614136565b612300565b348015610592575f80fd5b5061030a6105a1366004614156565b6123b0565b3480156105b1575f80fd5b506105c56105c0366004614196565b61251e565b60408051928352602083019190915201610225565b3480156105e5575f80fd5b5061030a6105f43660046141f6565b61295b565b348015610604575f80fd5b50610211610613366004613ca3565b60086020525f90815260409020546001600160a01b031681565b348015610638575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066b575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561069e575f80fd5b506102be612abe565b6002546001600160a01b90910460ff1611156106d6576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f83900361070a57604051637c946ed760e01b815260040160405180910390fd5b5f82900361072b5760405163d92e233d60e01b815260040160405180910390fd5b5f548085111561075d57604051637ae5968560e01b815260048101869052602481018290526044015b60405180910390fd5b60028054600160a81b900460ff169081600381111561077e5761077e614074565b148061079b5750600381600381111561079957610799614074565b145b8061081257506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156107e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061080b91906142a9565b60ff166002145b15610830576040516313d0ff5960e31b815260040160405180910390fd5b5f8581526008602090815260408083205481517fa8b2ae0200000000000000000000000000000000000000000000000000000000815291516001600160a01b039091169392849263a8b2ae0292600480830193928290030181865afa15801561089b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bf91906142c2565b90505f805f806108d18c8c8c88611681565b5f81815260066020526040902082905592965090945092509050821561094b57600354604051635e148f0960e11b8152600481018590526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015610934575f80fd5b505af1158015610946573d5f803e3d5ffd5b505050505b5f8415610b8157505f8b815260096020526040902054849080156109a5578181106109845761097a82826142ed565b90505f9150610994565b61098e81836142ed565b91505f90505b5f8d81526009602052604090208190555b8115610b72576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610a0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a3391906142c2565b60048054604051637ff796ab60e01b815230928101929092525f6024830152604482018690529192506001600160a01b0390911690637ff796ab906064016020604051808303815f875af1158015610a8d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab19190614306565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610b16573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3a91906142c2565b610b4491906142ed565b9050828114610b705760405163312b003360e01b81526004810182905260248101849052604401610754565b505b610b7f8d8d888e86612aea565b505b604080518d8152602081018d9052908101869052606081018290526080810185905233907f4095040bd441bb6761c0f983f93688032932a70ea67c45acf217522134d0e90c9060a00160405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050505050565b6002546001600160a01b90910460ff161115610c23576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179055610c4284848484612ce8565b5f5480861115610c6f57604051637ae5968560e01b81526004810187905260248101829052604401610754565b60028054600160a81b900460ff1690816003811115610c9057610c90614074565b1480610cad57506003816003811115610cab57610cab614074565b145b80610d2457506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015610cf9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d1d91906142a9565b60ff166002145b15610d42576040516313d0ff5960e31b815260040160405180910390fd5b6060806060610d528a8a8a612fe6565b825192955090935091505f9084906002908110610d7157610d71614325565b60200260200101511115610dfd5760035483516001600160a01b039091169063bc291e129085906002908110610da957610da9614325565b60200260200101516040518263ffffffff1660e01b8152600401610dcf91815260200190565b5f604051808303815f87803b158015610de6575f80fd5b505af1158015610df8573d5f803e3d5ffd5b505050505b5f835f81518110610e1057610e10614325565b60200260200101511115611094575f83600181518110610e3257610e32614325565b60200260200101511115611086576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610ea4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ec891906142c2565b60045485519192506001600160a01b031690637ff796ab9030905f9088906001908110610ef757610ef7614325565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303815f875af1158015610f6a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8e9190614306565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610ff3573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101791906142c2565b61102191906142ed565b90508360018151811061103657611036614325565b6020026020010151811461108457808460018151811061105857611058614325565b602002602001015160405163312b003360e01b8152600401610754929190918252602082015260400190565b505b6110948989848a858b613540565b336001600160a01b03167f4e8f98bab2ce9f2ab5649073958662ae3277689fdf749865832601431e3153ac8a8a85875f815181106110d4576110d4614325565b6020026020010151886001815181106110ef576110ef614325565b60200260200101518960028151811061110a5761110a614325565b6020026020010151604051611124969594939291906143ee565b60405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050565b6002546001600160a01b0316331461118b5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b821580611196575081155b8061119f575080155b156111bd57604051637c946ed760e01b815260040160405180910390fd5b4683036111e057604051633881b68960e01b815260048101849052602401610754565b5f838152600960205260408120546111f9908490614484565b90506bffffffffffffffffffffffff81111561123d57604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f8481526009602090815260408083208490556008909152908190205490517fac65ded2000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690819063ac65ded2906024015f604051808303815f87803b1580156112b4575f80fd5b505af11580156112c6573d5f803e3d5ffd5b505060408051888152602081018890529081018590528592507f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97591506060015b60405180910390a25050505050565b6002546001600160a01b031633146113555760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b600280548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16600160a81b83600381111561139557611395614074565b02179055507fa814f27828c0243d429ea8c7033cb10f0c825b9466fdc04f63e0cca26c28eb8a816040516113c99190614088565b60405180910390a150565b6005546001600160a01b031633146114145760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b807f00000000000000000000000000000000000000000000000000000000000000000361147657604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b600354604080517f14b19c5a00000000000000000000000000000000000000000000000000000000815290515f926001600160a01b0316916314b19c5a9160048083019260209291908290030181865afa1580156114d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114fa9190614497565b60035463ffffffff9190911691505f906001600160a01b031663d4ee9f8d6115236001856142ed565b6040518263ffffffff1660e01b815260040161154191815260200190565b602060405180830381865afa15801561155c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061158091906142c2565b90505f60035f9054906101000a90046001600160a01b03166001600160a01b031663d2b3996f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f79190614497565b63ffffffff1690505f62093a8061160e8385614484565b61161891906142ed565b905080421061164357604051637ae5968560e01b815242600482015260248101829052604401610754565b5f858152600760205260408082208690555186917f5a6a4aed2babbf3fe4cddce74151568eaac96f250cf910532f6528b1f6ee13d891a25050505050565b5f805f80865f036116a557604051637c946ed760e01b815260040160405180910390fd5b5f8690036116c65760405163d92e233d60e01b815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000860361172857604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5060408051808201825286815260209081018881528251808301899052905181840152825180820384018152606090910190925281519101205f61176c828a613b56565b6005546040516317d5e89d60e31b8152600481018b9052602481018c90529195509192506001600160a01b039091169063beaf44e8906044015f604051808303815f87803b1580156117bc575f80fd5b505af11580156117ce573d5f803e3d5ffd5b5083925050505b83811015611bb9575f818152600a602052604090205460ff16611bb157600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611839573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185d91906144d5565b606081015190915060ff16156118fc57604081015161ffff16158015611893575060208101516bffffffffffffffffffffffff16155b156118f75761ffff7f00000000000000000000000000000000000000000000000000000000000000001660408201526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660208201525b611902565b50611bb1565b60035460405163d4ee9f8d60e01b8152600481018490525f916001600160a01b03169063d4ee9f8d90602401602060405180830381865afa158015611949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061196d91906142c2565b600554604051630c88d47f60e41b8152600481018d9052602481018e9052604481018390529192505f9182916001600160a01b03169063c88d47f0906064016040805180830381865afa1580156119c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ea9190614558565b91509150805f03611a32575f858152600a60205260409020805460ff191660011790558351611a27906bffffffffffffffffffffffff168a614484565b985050505050611bb1565b83515f9081906bffffffffffffffffffffffff168184821115611a5f57611a5985836142ed565b90508491505b6040880151611a789061ffff16655af3107a400061457a565b861015611aae57670de0b6b3a764000086611a938484614484565b611a9d919061457a565b611aa791906145a5565b9250611b9c565b670de0b6b3a7640000611ac1878461457a565b611acb91906145a5565b9350670de0b6b3a7640000611ae0878361457a565b611aea91906145a5565b925087602001516bffffffffffffffffffffffff16915081841115611b2357611b1382856142ed565b611b1d9084614484565b92508193505b60128f1015611b8f575f8f6012611b3a91906142ed565b611b4590600a614698565b611b4f90866145a5565b90508f6012611b5e91906142ed565b611b6990600a614698565b611b73908261457a565b9050611b7f81866142ed565b611b899085614484565b90945092505b611b99848f614484565b9d505b611ba6838e614484565b9c5050505050505050505b6001016117d5565b5050945094509450949050565b5f838152600860205260409020546001600160a01b0316338114611c27576040517fdeeeedec0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0382166024820152604401610754565b5f84815260096020526040812054611c40908590614484565b90506bffffffffffffffffffffffff811115611c8457604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f85815260096020908152604091829020839055815187815290810186905290810182905283907f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97590606001611306565b6002546001600160a01b90910460ff161115611d04576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f80548190611d47907f000000000000000000000000000000000000000000000000000000000000000090613b56565b6005546040516317d5e89d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201529294509092506001600160a01b03169063beaf44e8906044015f604051808303815f87803b158015611db3575f80fd5b505af1158015611dc5573d5f803e3d5ffd5b50507f00000000000000000000000000000000000000000000000000000000000000005f90815260066020526040812084905591508390505b82811015611fb557600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611e4d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e7191906144d5565b60035460405163d4ee9f8d60e01b8152600481018590529192505f916001600160a01b039091169063d4ee9f8d90602401602060405180830381865afa158015611ebd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ee191906142c2565b600554604051630c88d47f60e41b81527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604481018390529192505f916001600160a01b039091169063c88d47f0906064016040805180830381865afa158015611f58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f7c9190614558565b508351909150611f9b9082906bffffffffffffffffffffffff1661457a565b611fa59086614484565b9450505050806001019050611dfe565b50611fc8670de0b6b3a7640000826145a5565b9050801561202a57600354604051635e148f0960e11b8152600481018390526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015612013575f80fd5b505af1158015612025573d5f803e3d5ffd5b505050505b60405181815233907f2a8de497d698d6869cb0844411788378e76214d03a541eec6ba514b795d9f42e9060200160405180910390a250506002805460ff60a01b1916600160a01b17905550565b6005546001600160a01b031633146120b75760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b60028054600160a81b900460ff16908160038111156120d8576120d8614074565b14806120f5575060038160038111156120f3576120f3614074565b145b8061216c57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015612141573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061216591906142a9565b60ff166002145b1561218a576040516313d0ff5960e31b815260040160405180910390fd5b60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121fe9190614497565b5f8381526006602052604080822063ffffffff93909316909255905183917f5381b67b592d2dc84b61238222ab88ee04db3b3a082894a445c4e5cfa8ba11be91a25050565b6002546001600160a01b031633146122835760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b0381166122aa5760405163d92e233d60e01b815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b905f90a250565b6002546001600160a01b031633146123405760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b81158061234b575080155b1561236957604051637c946ed760e01b815260040160405180910390fd5b5f829055600181905560408051838152602081018390527f61f6c4cc9665a257352c0b46189ffc2ae6fbbc11e155ff20901217ff203a517e91015b60405180910390a15050565b6002546001600160a01b031633146123f05760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b03831615612453576003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385169081179091556040517f4672fe7e13cfb163442d0b729b5733fb3efafc66cbe3677eac9940eb41c284c2905f90a25b6001600160a01b038216156124b6576004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040517f7dae230f18360d76a040c81f050aa14eb9d6dc7901b20fc5d855e2a20fe814d1905f90a25b6001600160a01b03811615612519576005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f04a606379838ed6fc83fd189eea9d1835b5eff05035c4b74622911ea2ae6b217905f90a25b505050565b5f806001600260149054906101000a900460ff1660ff161115612554576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179081905560ff600160a81b90910416600181600381111561258857612588614074565b14806125a5575060038160038111156125a3576125a3614074565b145b8061261c57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156125f1573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261591906142a9565b60ff166002145b1561263a576040516313d0ff5960e31b815260040160405180910390fd5b6003546040517f2e070f540000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632e070f5490612687903390899089906004016146a3565b60408051808303815f875af11580156126a2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126c69190614558565b90935091505f806126d78486614484565b11156128af575f831561276d576040516370a0823160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612746573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061276a91906142c2565b90505b60048054604051637ff796ab60e01b8152339281019290925260248201879052604482018690526001600160a01b031690637ff796ab906064016020604051808303815f875af11580156127c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127e79190614306565b915083156128ad576040516370a0823160e01b815233600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612853573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061287791906142c2565b61288191906142ed565b90508381146128ad5760405163312b003360e01b81526004810182905260248101859052604401610754565b505b806128f6576040517f942dc9da0000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606401610754565b336001600160a01b03167fbe9ae4aaa6e41ee5c966cad91e78ec7202d0062fe8c9564b28629a614003cf828585898960405161293594939291906146e0565b60405180910390a250506002805460ff60a01b1916600160a01b17905590939092509050565b6002546001600160a01b0316331461299b5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b815115806129ab57508051825114155b156129d657815181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f5b8151811015612a8c578181815181106129f3576129f3614325565b60200260200101515f03612a1a57604051637c946ed760e01b815260040160405180910390fd5b828181518110612a2c57612a2c614325565b602002602001015160085f848481518110612a4957612a49614325565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508060010190506129d8565b507fe87460f6c400fa0166984512586d7bdf03a3230bbadf9651f27f08716dd77fa582826040516123a4929190614753565b6024612ad3600267ffffffffffffffff614780565b612add91906147a6565b67ffffffffffffffff1681565b5f858152600860205260409020546001600160a01b03168115612bb2576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303815f875af1158015612b8c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bb09190614306565b505b6024612bc7600267ffffffffffffffff614780565b612bd191906147a6565b67ffffffffffffffff168611612c64576040517fb2267a7b00000000000000000000000000000000000000000000000000000000815285906001600160a01b0383169063b2267a7b903490612c309085908a908a908a906004016147fc565b5f604051808303818588803b158015612c47575f80fd5b505af1158015612c59573d5f803e3d5ffd5b505050505050612ce0565b6040517f6585ecdc0000000000000000000000000000000000000000000000000000000081526001600160a01b03821690636585ecdc903490612cb1908990899089908990600401614834565b5f604051808303818588803b158015612cc8575f80fd5b505af1158015612cda573d5f803e3d5ffd5b50505050505b505050505050565b8251845114612d1757835183516040516308151c1160e41b815260048101929092526024820152604401610754565b8151845114612d4657835182516040516308151c1160e41b815260048101929092526024820152604401610754565b8051845114612d7557835181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f805f5b8651811015612fbc57868181518110612d9457612d94614325565b60200260200101518310612dd857868181518110612db457612db4614325565b6020026020010151604051633881b68960e01b815260040161075491815260200190565b868181518110612dea57612dea614325565b60200260200101519250858181518110612e0657612e06614325565b6020026020010151515f03612e2e57604051637c946ed760e01b815260040160405180910390fd5b838181518110612e4057612e40614325565b602002602001015182612e539190614484565b91505f600154905080878381518110612e6e57612e6e614325565b6020026020010151511115612ebd57868281518110612e8f57612e8f614325565b60200260200101515181604051637ae5968560e01b8152600401610754929190918252602082015260400190565b5f805b888481518110612ed257612ed2614325565b602002602001015151811015612fae57888481518110612ef457612ef4614325565b60200260200101518181518110612f0d57612f0d614325565b60200260200101515f1c825f1c10612f6e57888481518110612f3157612f31614325565b60200260200101518181518110612f4a57612f4a614325565b6020026020010151604051636aba776560e11b815260040161075491815260200190565b888481518110612f8057612f80614325565b60200260200101518181518110612f9957612f99614325565b60200260200101519150806001019050612ec0565b505050806001019050612d79565b50803414612ce05760405163312b003360e01b815234600482015260248101829052604401610754565b6040805160038082526080820190925260609182918291602082018380368337019050509250845167ffffffffffffffff81111561302657613026613cba565b60405190808252806020026020018201604052801561305957816020015b60608152602001906001900390816130445790505b509150845167ffffffffffffffff81111561307657613076613cba565b60405190808252806020026020018201604052801561309f578160200160208202803683370190505b5090505f5b8551811015613536575f60085f8884815181106130c3576130c3614325565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f816001600160a01b031663a8b2ae026040518163ffffffff1660e01b8152600401602060405180830381865afa15801561312a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061314e91906142c2565b905086838151811061316257613162614325565b60200260200101515167ffffffffffffffff81111561318357613183613cba565b6040519080825280602002602001820160405280156131ac578160200160208202803683370190505b508584815181106131bf576131bf614325565b60200260200101819052505f5b8784815181106131de576131de614325565b6020026020010151518110156133c5577f000000000000000000000000000000000000000000000000000000000000000088858151811061322157613221614325565b6020026020010151828151811061323a5761323a614325565b60200260200101510361328257604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5f805f806132dd8e8e8a8151811061329c5761329c614325565b60200260200101518e8b815181106132b6576132b6614325565b602002602001015188815181106132cf576132cf614325565b602002602001015189611681565b5f8181526006602052604090208290558d519397509195509350915084908b908a90811061330d5761330d614325565b6020026020010151868151811061332657613326614325565b6020026020010181815250508389898151811061334557613345614325565b602002602001018181516133599190614484565b9052508a5184908c905f9061337057613370614325565b602002602001018181516133849190614484565b9052508a5183908c90600290811061339e5761339e614325565b602002602001018181516133b29190614484565b90525050600190930192506131cc915050565b505f8484815181106133d9576133d9614325565b602002602001015111156134e8575f60095f8a86815181106133fd576133fd614325565b602002602001015181526020019081526020015f205490505f8111156134e65784848151811061342f5761342f614325565b602002602001015181106134885784848151811061344f5761344f614325565b60200260200101518161346291906142ed565b90505f85858151811061347757613477614325565b6020026020010181815250506134b6565b8085858151811061349b5761349b614325565b602002602001018181516134af91906142ed565b9052505f90505b8060095f8b87815181106134cc576134cc614325565b602002602001015181526020019081526020015f20819055505b505b8383815181106134fa576134fa614325565b60200260200101518660018151811061351557613515614325565b602002602001018181516135299190614484565b90525050506001016130a4565b5093509350939050565b5f5b8651811015613b4d575f60085f89848151811061356157613561614325565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f84838151811061359e5761359e614325565b60200260200101511115613669577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb828685815181106135ee576135ee614325565b60200260200101516040518363ffffffff1660e01b81526004016136279291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af1158015613643573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136679190614306565b505b5f8088848151811061367d5761367d614325565b60200260200101515167ffffffffffffffff81111561369e5761369e613cba565b6040519080825280602002602001820160405280156136c7578160200160208202803683370190505b5090505f5b8985815181106136de576136de614325565b602002602001015151811015613760575f89868151811061370157613701614325565b6020026020010151828151811061371a5761371a614325565b6020026020010151111561375857600182828151811061373c5761373c614325565b9115156020928302919091019091015261375583614852565b92505b6001016136cc565b50815f0361377057505050613b45565b5f8267ffffffffffffffff81111561378a5761378a613cba565b6040519080825280602002602001820160405280156137b3578160200160208202803683370190505b5090505f8367ffffffffffffffff8111156137d0576137d0613cba565b6040519080825280602002602001820160405280156137f9578160200160208202803683370190505b5090505f805b8c888151811061381157613811614325565b6020026020010151518110156138f55784818151811061383357613833614325565b6020026020010151156138ed578c888151811061385257613852614325565b6020026020010151818151811061386b5761386b614325565b602002602001015184838151811061388557613885614325565b6020026020010181815250508b88815181106138a3576138a3614325565b602002602001015181815181106138bc576138bc614325565b60200260200101518383815181106138d6576138d6614325565b60209081029190910101526138ea82614852565b91505b6001016137ff565b50602461390b600267ffffffffffffffff614780565b61391591906147a6565b67ffffffffffffffff168d888151811061393157613931614325565b602002602001015111613a91575f835167ffffffffffffffff81111561395957613959613cba565b604051908082528060200260200182016040528015613982578160200160208202803683370190505b5090505f5b84518110156139de578481815181106139a2576139a2614325565b60200260200101515f1c8282815181106139be576139be614325565b6001600160a01b0390921660209283029190910190910152600101613987565b50866001600160a01b031663bde526618a8a81518110613a0057613a00614325565b602002602001015183868f8d81518110613a1c57613a1c614325565b60200260200101518f8e81518110613a3657613a36614325565b60200260200101516040518663ffffffff1660e01b8152600401613a5d949392919061486a565b5f604051808303818588803b158015613a74575f80fd5b505af1158015613a86573d5f803e3d5ffd5b505050505050613b3e565b856001600160a01b03166355442b59898981518110613ab257613ab2614325565b602002602001015185858e8c81518110613ace57613ace614325565b60200260200101518e8d81518110613ae857613ae8614325565b60200260200101516040518663ffffffff1660e01b8152600401613b0f94939291906148b4565b5f604051808303818588803b158015613b26575f80fd5b505af1158015613b38573d5f803e3d5ffd5b50505050505b5050505050505b600101613542565b50505050505050565b5f805f60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ba9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613bcd9190614497565b5f86815260066020526040812054945063ffffffff919091169150839003613c0857604051637c946ed760e01b815260040160405180910390fd5b808303613c3d5782613c1b6001836142ed565b604051637ae5968560e01b815260048101929092526024820152604401610754565b5f858152600760205260409020548015801590613c5a5750808410155b15613c6b5783613c1b6001836142ed565b613c758585614484565b92505f81118015613c8557508083115b15613c8e578092505b81831115613c9a578192505b50509250929050565b5f60208284031215613cb3575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613cf757613cf7613cba565b604052919050565b5f82601f830112613d0e575f80fd5b813567ffffffffffffffff811115613d2857613d28613cba565b613d3b601f8201601f1916602001613cce565b818152846020838601011115613d4f575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215613d7e575f80fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115613da9575f80fd5b613db587828801613cff565b91505092959194509250565b5f67ffffffffffffffff821115613dda57613dda613cba565b5060051b60200190565b5f82601f830112613df3575f80fd5b81356020613e08613e0383613dc1565b613cce565b8083825260208201915060208460051b870101935086841115613e29575f80fd5b602086015b84811015613e455780358352918301918301613e2e565b509695505050505050565b5f82601f830112613e5f575f80fd5b81356020613e6f613e0383613dc1565b82815260059290921b84018101918181019086841115613e8d575f80fd5b8286015b84811015613e4557803567ffffffffffffffff811115613eaf575f80fd5b613ebd8986838b0101613cff565b845250918301918301613e91565b5f805f805f60a08688031215613edf575f80fd5b8535945067ffffffffffffffff8060208801351115613efc575f80fd5b613f0c8860208901358901613de4565b94508060408801351115613f1e575f80fd5b6040870135870188601f820112613f33575f80fd5b613f40613e038235613dc1565b81358082526020808301929160051b8401018b1015613f5d575f80fd5b602083015b6020843560051b850101811015613ff7578481351115613f80575f80fd5b803584018c603f820112613f92575f80fd5b613fa2613e036020830135613dc1565b602082810135808352908201919060051b83016040018f811115613fc4575f80fd5b6040840193505b80841015613fe6578335835260209384019390920191613fcb565b508552505060209283019201613f62565b5095505050606087013581101561400c575f80fd5b61401c8860608901358901613e50565b9250806080880135111561402e575f80fd5b5061403f8760808801358801613de4565b90509295509295909350565b5f805f6060848603121561405d575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106140a857634e487b7160e01b5f52602160045260245ffd5b91905290565b5f602082840312156140be575f80fd5b8135600481106140cc575f80fd5b9392505050565b5f805f80608085870312156140e6575f80fd5b5050823594602084013594506040840135936060013592509050565b80356001600160a01b0381168114614118575f80fd5b919050565b5f6020828403121561412d575f80fd5b6140cc82614102565b5f8060408385031215614147575f80fd5b50508035926020909101359150565b5f805f60608486031215614168575f80fd5b61417184614102565b925061417f60208501614102565b915061418d60408501614102565b90509250925092565b5f80604083850312156141a7575f80fd5b823567ffffffffffffffff808211156141be575f80fd5b6141ca86838701613de4565b935060208501359150808211156141df575f80fd5b506141ec85828601613de4565b9150509250929050565b5f8060408385031215614207575f80fd5b823567ffffffffffffffff8082111561421e575f80fd5b818501915085601f830112614231575f80fd5b81356020614241613e0383613dc1565b82815260059290921b8401810191818101908984111561425f575f80fd5b948201945b838610156142845761427586614102565b82529482019490820190614264565b965050860135925050808211156141df575f80fd5b805160ff81168114614118575f80fd5b5f602082840312156142b9575f80fd5b6140cc82614299565b5f602082840312156142d2575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115614300576143006142d9565b92915050565b5f60208284031215614316575f80fd5b815180151581146140cc575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f815180845260208085019450602084015f5b838110156143685781518752958201959082019060010161434c565b509495945050505050565b5f82825180855260208086019550808260051b8401018186015f5b848110156143e157858303601f190189528151805180855290850190858501905f5b818110156143cc578351835292870192918701916001016143b0565b5050998501999350509083019060010161438e565b5090979650505050505050565b60c081525f61440060c0830189614339565b6020838203818501528189518084528284019150828160051b850101838c015f5b8381101561444f57601f1987840301855261443d838351614339565b94860194925090850190600101614421565b50508681036040880152614463818c614373565b606088019a909a525050505060808301949094525060a00152509392505050565b80820180821115614300576143006142d9565b5f602082840312156144a7575f80fd5b815163ffffffff811681146140cc575f80fd5b80516bffffffffffffffffffffffff81168114614118575f80fd5b5f608082840312156144e5575f80fd5b6040516080810181811067ffffffffffffffff8211171561450857614508613cba565b604052614514836144ba565b8152614522602084016144ba565b6020820152604083015161ffff8116811461453b575f80fd5b604082015261454c60608401614299565b60608201529392505050565b5f8060408385031215614569575f80fd5b505080516020909101519092909150565b8082028115828204841417614300576143006142d9565b634e487b7160e01b5f52601260045260245ffd5b5f826145b3576145b3614591565b500490565b600181815b808511156145f257815f19048211156145d8576145d86142d9565b808516156145e557918102915b93841c93908002906145bd565b509250929050565b5f8261460857506001614300565b8161461457505f614300565b816001811461462a576002811461463457614650565b6001915050614300565b60ff841115614645576146456142d9565b50506001821b614300565b5060208310610133831016604e8410600b8410161715614673575081810a614300565b61467d83836145b8565b805f1904821115614690576146906142d9565b029392505050565b5f6140cc83836145fa565b6001600160a01b0384168152606060208201525f6146c46060830185614339565b82810360408401526146d68185614339565b9695505050505050565b848152836020820152608060408201525f6146fe6080830185614339565b82810360608401526147108185614339565b979650505050505050565b5f815180845260208085019450602084015f5b838110156143685781516001600160a01b03168752958201959082019060010161472e565b604081525f614765604083018561471b565b82810360208401526147778185614339565b95945050505050565b5f67ffffffffffffffff8084168061479a5761479a614591565b92169190910492915050565b67ffffffffffffffff8281168282160390808211156147c7576147c76142d9565b5092915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152836020820152608060408201525f61482360808301856147ce565b905082606083015295945050505050565b848152836020820152608060408201525f61482360808301856147ce565b5f60018201614863576148636142d9565b5060010190565b608081525f61487c608083018761471b565b828103602084015261488e8187614339565b905082810360408401526148a281866147ce565b91505082606083015295945050505050565b608081525f61487c608083018761433956fea26469706673582212204f62b365dfacc16118c8e0397d13c78fb01e19f895ea8e406a87973c6c961c4c64736f6c63430008190033",
+ "deployedBytecode": "0x6080604052600436106101da575f3560e01c806379bc81dd116100fd578063bc7d5c5c11610092578063dcb5ccc411610062578063dcb5ccc4146105f9578063e09177781461062d578063e6be59e714610660578063f4da12ba14610693575f80fd5b8063bc7d5c5c14610568578063d529779314610587578063d7accbcc146105a6578063d8bf69bf146105da575f80fd5b80639649a35c116100cd5780639649a35c146104eb578063a5edd4fc146104ff578063a6f9dae11461051e578063bb78678f1461053d575f80fd5b806379bc81dd1461046e5780638513e77d1461048d5780638833c205146104b85780638da5cb5b146104cc575f80fd5b80633c18d1dd1161017357806361d027b31161014357806361d027b3146103d257806363096509146103f157806363c4d28e14610410578063777e49c91461042f575f80fd5b80633c18d1dd146103345780634ac7251d146103675780635a55a482146103865780635c975abb146103a5575f80fd5b80632ad923dc116101ae5780632ad923dc146102cc5780632c0f3f29146102f757806334be5af41461030c5780633907196c14610321575f80fd5b806231d115146101de5780630d17db111461022e5780630d3241ee1461026c5780632a3bb6931461028b575b5f80fd5b3480156101e9575f80fd5b506102117f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610239575f80fd5b5061025c610248366004613ca3565b600a6020525f908152604090205460ff1681565b6040519015158152602001610225565b348015610277575f80fd5b50600554610211906001600160a01b031681565b348015610296575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610225565b3480156102d7575f80fd5b506102be6102e6366004613ca3565b60066020525f908152604090205481565b61030a610305366004613d6b565b6106a7565b005b348015610317575f80fd5b506102be60015481565b61030a61032f366004613ecb565b610bf4565b34801561033f575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b348015610372575f80fd5b50600354610211906001600160a01b031681565b348015610391575f80fd5b5061030a6103a036600461404b565b61114b565b3480156103b0575f80fd5b506002546103c590600160a81b900460ff1681565b6040516102259190614088565b3480156103dd575f80fd5b50600454610211906001600160a01b031681565b3480156103fc575f80fd5b5061030a61040b3660046140ae565b611315565b34801561041b575f80fd5b5061030a61042a366004613ca3565b6113d4565b34801561043a575f80fd5b5061044e6104493660046140d3565b611681565b604080519485526020850193909352918301526060820152608001610225565b348015610479575f80fd5b5061030a61048836600461404b565b611bc6565b348015610498575f80fd5b506102be6104a7366004613ca3565b60076020525f908152604090205481565b3480156104c3575f80fd5b506102be5f5481565b3480156104d7575f80fd5b50600254610211906001600160a01b031681565b3480156104f6575f80fd5b5061030a611cd5565b34801561050a575f80fd5b5061030a610519366004613ca3565b612077565b348015610529575f80fd5b5061030a61053836600461411d565b612243565b348015610548575f80fd5b506102be610557366004613ca3565b60096020525f908152604090205481565b348015610573575f80fd5b5061030a610582366004614136565b612300565b348015610592575f80fd5b5061030a6105a1366004614156565b6123b0565b3480156105b1575f80fd5b506105c56105c0366004614196565b61251e565b60408051928352602083019190915201610225565b3480156105e5575f80fd5b5061030a6105f43660046141f6565b61295b565b348015610604575f80fd5b50610211610613366004613ca3565b60086020525f90815260409020546001600160a01b031681565b348015610638575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066b575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561069e575f80fd5b506102be612abe565b6002546001600160a01b90910460ff1611156106d6576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f83900361070a57604051637c946ed760e01b815260040160405180910390fd5b5f82900361072b5760405163d92e233d60e01b815260040160405180910390fd5b5f548085111561075d57604051637ae5968560e01b815260048101869052602481018290526044015b60405180910390fd5b60028054600160a81b900460ff169081600381111561077e5761077e614074565b148061079b5750600381600381111561079957610799614074565b145b8061081257506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156107e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061080b91906142a9565b60ff166002145b15610830576040516313d0ff5960e31b815260040160405180910390fd5b5f8581526008602090815260408083205481517fa8b2ae0200000000000000000000000000000000000000000000000000000000815291516001600160a01b039091169392849263a8b2ae0292600480830193928290030181865afa15801561089b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bf91906142c2565b90505f805f806108d18c8c8c88611681565b5f81815260066020526040902082905592965090945092509050821561094b57600354604051635e148f0960e11b8152600481018590526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015610934575f80fd5b505af1158015610946573d5f803e3d5ffd5b505050505b5f8415610b8157505f8b815260096020526040902054849080156109a5578181106109845761097a82826142ed565b90505f9150610994565b61098e81836142ed565b91505f90505b5f8d81526009602052604090208190555b8115610b72576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610a0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a3391906142c2565b60048054604051637ff796ab60e01b815230928101929092525f6024830152604482018690529192506001600160a01b0390911690637ff796ab906064016020604051808303815f875af1158015610a8d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab19190614306565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610b16573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3a91906142c2565b610b4491906142ed565b9050828114610b705760405163312b003360e01b81526004810182905260248101849052604401610754565b505b610b7f8d8d888e86612aea565b505b604080518d8152602081018d9052908101869052606081018290526080810185905233907f4095040bd441bb6761c0f983f93688032932a70ea67c45acf217522134d0e90c9060a00160405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050505050565b6002546001600160a01b90910460ff161115610c23576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179055610c4284848484612ce8565b5f5480861115610c6f57604051637ae5968560e01b81526004810187905260248101829052604401610754565b60028054600160a81b900460ff1690816003811115610c9057610c90614074565b1480610cad57506003816003811115610cab57610cab614074565b145b80610d2457506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015610cf9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d1d91906142a9565b60ff166002145b15610d42576040516313d0ff5960e31b815260040160405180910390fd5b6060806060610d528a8a8a612fe6565b825192955090935091505f9084906002908110610d7157610d71614325565b60200260200101511115610dfd5760035483516001600160a01b039091169063bc291e129085906002908110610da957610da9614325565b60200260200101516040518263ffffffff1660e01b8152600401610dcf91815260200190565b5f604051808303815f87803b158015610de6575f80fd5b505af1158015610df8573d5f803e3d5ffd5b505050505b5f835f81518110610e1057610e10614325565b60200260200101511115611094575f83600181518110610e3257610e32614325565b60200260200101511115611086576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610ea4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ec891906142c2565b60045485519192506001600160a01b031690637ff796ab9030905f9088906001908110610ef757610ef7614325565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303815f875af1158015610f6a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8e9190614306565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610ff3573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101791906142c2565b61102191906142ed565b90508360018151811061103657611036614325565b6020026020010151811461108457808460018151811061105857611058614325565b602002602001015160405163312b003360e01b8152600401610754929190918252602082015260400190565b505b6110948989848a858b613540565b336001600160a01b03167f4e8f98bab2ce9f2ab5649073958662ae3277689fdf749865832601431e3153ac8a8a85875f815181106110d4576110d4614325565b6020026020010151886001815181106110ef576110ef614325565b60200260200101518960028151811061110a5761110a614325565b6020026020010151604051611124969594939291906143ee565b60405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050565b6002546001600160a01b0316331461118b5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b821580611196575081155b8061119f575080155b156111bd57604051637c946ed760e01b815260040160405180910390fd5b4683036111e057604051633881b68960e01b815260048101849052602401610754565b5f838152600960205260408120546111f9908490614484565b90506bffffffffffffffffffffffff81111561123d57604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f8481526009602090815260408083208490556008909152908190205490517fac65ded2000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690819063ac65ded2906024015f604051808303815f87803b1580156112b4575f80fd5b505af11580156112c6573d5f803e3d5ffd5b505060408051888152602081018890529081018590528592507f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97591506060015b60405180910390a25050505050565b6002546001600160a01b031633146113555760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b600280548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16600160a81b83600381111561139557611395614074565b02179055507fa814f27828c0243d429ea8c7033cb10f0c825b9466fdc04f63e0cca26c28eb8a816040516113c99190614088565b60405180910390a150565b6005546001600160a01b031633146114145760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b807f00000000000000000000000000000000000000000000000000000000000000000361147657604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b600354604080517f14b19c5a00000000000000000000000000000000000000000000000000000000815290515f926001600160a01b0316916314b19c5a9160048083019260209291908290030181865afa1580156114d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114fa9190614497565b60035463ffffffff9190911691505f906001600160a01b031663d4ee9f8d6115236001856142ed565b6040518263ffffffff1660e01b815260040161154191815260200190565b602060405180830381865afa15801561155c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061158091906142c2565b90505f60035f9054906101000a90046001600160a01b03166001600160a01b031663d2b3996f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f79190614497565b63ffffffff1690505f62093a8061160e8385614484565b61161891906142ed565b905080421061164357604051637ae5968560e01b815242600482015260248101829052604401610754565b5f858152600760205260408082208690555186917f5a6a4aed2babbf3fe4cddce74151568eaac96f250cf910532f6528b1f6ee13d891a25050505050565b5f805f80865f036116a557604051637c946ed760e01b815260040160405180910390fd5b5f8690036116c65760405163d92e233d60e01b815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000860361172857604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5060408051808201825286815260209081018881528251808301899052905181840152825180820384018152606090910190925281519101205f61176c828a613b56565b6005546040516317d5e89d60e31b8152600481018b9052602481018c90529195509192506001600160a01b039091169063beaf44e8906044015f604051808303815f87803b1580156117bc575f80fd5b505af11580156117ce573d5f803e3d5ffd5b5083925050505b83811015611bb9575f818152600a602052604090205460ff16611bb157600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611839573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185d91906144d5565b606081015190915060ff16156118fc57604081015161ffff16158015611893575060208101516bffffffffffffffffffffffff16155b156118f75761ffff7f00000000000000000000000000000000000000000000000000000000000000001660408201526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660208201525b611902565b50611bb1565b60035460405163d4ee9f8d60e01b8152600481018490525f916001600160a01b03169063d4ee9f8d90602401602060405180830381865afa158015611949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061196d91906142c2565b600554604051630c88d47f60e41b8152600481018d9052602481018e9052604481018390529192505f9182916001600160a01b03169063c88d47f0906064016040805180830381865afa1580156119c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ea9190614558565b91509150805f03611a32575f858152600a60205260409020805460ff191660011790558351611a27906bffffffffffffffffffffffff168a614484565b985050505050611bb1565b83515f9081906bffffffffffffffffffffffff168184821115611a5f57611a5985836142ed565b90508491505b6040880151611a789061ffff16655af3107a400061457a565b861015611aae57670de0b6b3a764000086611a938484614484565b611a9d919061457a565b611aa791906145a5565b9250611b9c565b670de0b6b3a7640000611ac1878461457a565b611acb91906145a5565b9350670de0b6b3a7640000611ae0878361457a565b611aea91906145a5565b925087602001516bffffffffffffffffffffffff16915081841115611b2357611b1382856142ed565b611b1d9084614484565b92508193505b60128f1015611b8f575f8f6012611b3a91906142ed565b611b4590600a614698565b611b4f90866145a5565b90508f6012611b5e91906142ed565b611b6990600a614698565b611b73908261457a565b9050611b7f81866142ed565b611b899085614484565b90945092505b611b99848f614484565b9d505b611ba6838e614484565b9c5050505050505050505b6001016117d5565b5050945094509450949050565b5f838152600860205260409020546001600160a01b0316338114611c27576040517fdeeeedec0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0382166024820152604401610754565b5f84815260096020526040812054611c40908590614484565b90506bffffffffffffffffffffffff811115611c8457604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f85815260096020908152604091829020839055815187815290810186905290810182905283907f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97590606001611306565b6002546001600160a01b90910460ff161115611d04576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f80548190611d47907f000000000000000000000000000000000000000000000000000000000000000090613b56565b6005546040516317d5e89d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201529294509092506001600160a01b03169063beaf44e8906044015f604051808303815f87803b158015611db3575f80fd5b505af1158015611dc5573d5f803e3d5ffd5b50507f00000000000000000000000000000000000000000000000000000000000000005f90815260066020526040812084905591508390505b82811015611fb557600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611e4d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e7191906144d5565b60035460405163d4ee9f8d60e01b8152600481018590529192505f916001600160a01b039091169063d4ee9f8d90602401602060405180830381865afa158015611ebd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ee191906142c2565b600554604051630c88d47f60e41b81527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604481018390529192505f916001600160a01b039091169063c88d47f0906064016040805180830381865afa158015611f58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f7c9190614558565b508351909150611f9b9082906bffffffffffffffffffffffff1661457a565b611fa59086614484565b9450505050806001019050611dfe565b50611fc8670de0b6b3a7640000826145a5565b9050801561202a57600354604051635e148f0960e11b8152600481018390526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015612013575f80fd5b505af1158015612025573d5f803e3d5ffd5b505050505b60405181815233907f2a8de497d698d6869cb0844411788378e76214d03a541eec6ba514b795d9f42e9060200160405180910390a250506002805460ff60a01b1916600160a01b17905550565b6005546001600160a01b031633146120b75760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b60028054600160a81b900460ff16908160038111156120d8576120d8614074565b14806120f5575060038160038111156120f3576120f3614074565b145b8061216c57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015612141573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061216591906142a9565b60ff166002145b1561218a576040516313d0ff5960e31b815260040160405180910390fd5b60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121fe9190614497565b5f8381526006602052604080822063ffffffff93909316909255905183917f5381b67b592d2dc84b61238222ab88ee04db3b3a082894a445c4e5cfa8ba11be91a25050565b6002546001600160a01b031633146122835760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b0381166122aa5760405163d92e233d60e01b815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b905f90a250565b6002546001600160a01b031633146123405760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b81158061234b575080155b1561236957604051637c946ed760e01b815260040160405180910390fd5b5f829055600181905560408051838152602081018390527f61f6c4cc9665a257352c0b46189ffc2ae6fbbc11e155ff20901217ff203a517e91015b60405180910390a15050565b6002546001600160a01b031633146123f05760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b03831615612453576003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385169081179091556040517f4672fe7e13cfb163442d0b729b5733fb3efafc66cbe3677eac9940eb41c284c2905f90a25b6001600160a01b038216156124b6576004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040517f7dae230f18360d76a040c81f050aa14eb9d6dc7901b20fc5d855e2a20fe814d1905f90a25b6001600160a01b03811615612519576005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f04a606379838ed6fc83fd189eea9d1835b5eff05035c4b74622911ea2ae6b217905f90a25b505050565b5f806001600260149054906101000a900460ff1660ff161115612554576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179081905560ff600160a81b90910416600181600381111561258857612588614074565b14806125a5575060038160038111156125a3576125a3614074565b145b8061261c57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156125f1573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261591906142a9565b60ff166002145b1561263a576040516313d0ff5960e31b815260040160405180910390fd5b6003546040517f2e070f540000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632e070f5490612687903390899089906004016146a3565b60408051808303815f875af11580156126a2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126c69190614558565b90935091505f806126d78486614484565b11156128af575f831561276d576040516370a0823160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612746573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061276a91906142c2565b90505b60048054604051637ff796ab60e01b8152339281019290925260248201879052604482018690526001600160a01b031690637ff796ab906064016020604051808303815f875af11580156127c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127e79190614306565b915083156128ad576040516370a0823160e01b815233600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612853573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061287791906142c2565b61288191906142ed565b90508381146128ad5760405163312b003360e01b81526004810182905260248101859052604401610754565b505b806128f6576040517f942dc9da0000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606401610754565b336001600160a01b03167fbe9ae4aaa6e41ee5c966cad91e78ec7202d0062fe8c9564b28629a614003cf828585898960405161293594939291906146e0565b60405180910390a250506002805460ff60a01b1916600160a01b17905590939092509050565b6002546001600160a01b0316331461299b5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b815115806129ab57508051825114155b156129d657815181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f5b8151811015612a8c578181815181106129f3576129f3614325565b60200260200101515f03612a1a57604051637c946ed760e01b815260040160405180910390fd5b828181518110612a2c57612a2c614325565b602002602001015160085f848481518110612a4957612a49614325565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508060010190506129d8565b507fe87460f6c400fa0166984512586d7bdf03a3230bbadf9651f27f08716dd77fa582826040516123a4929190614753565b6024612ad3600267ffffffffffffffff614780565b612add91906147a6565b67ffffffffffffffff1681565b5f858152600860205260409020546001600160a01b03168115612bb2576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303815f875af1158015612b8c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bb09190614306565b505b6024612bc7600267ffffffffffffffff614780565b612bd191906147a6565b67ffffffffffffffff168611612c64576040517fb2267a7b00000000000000000000000000000000000000000000000000000000815285906001600160a01b0383169063b2267a7b903490612c309085908a908a908a906004016147fc565b5f604051808303818588803b158015612c47575f80fd5b505af1158015612c59573d5f803e3d5ffd5b505050505050612ce0565b6040517f6585ecdc0000000000000000000000000000000000000000000000000000000081526001600160a01b03821690636585ecdc903490612cb1908990899089908990600401614834565b5f604051808303818588803b158015612cc8575f80fd5b505af1158015612cda573d5f803e3d5ffd5b50505050505b505050505050565b8251845114612d1757835183516040516308151c1160e41b815260048101929092526024820152604401610754565b8151845114612d4657835182516040516308151c1160e41b815260048101929092526024820152604401610754565b8051845114612d7557835181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f805f5b8651811015612fbc57868181518110612d9457612d94614325565b60200260200101518310612dd857868181518110612db457612db4614325565b6020026020010151604051633881b68960e01b815260040161075491815260200190565b868181518110612dea57612dea614325565b60200260200101519250858181518110612e0657612e06614325565b6020026020010151515f03612e2e57604051637c946ed760e01b815260040160405180910390fd5b838181518110612e4057612e40614325565b602002602001015182612e539190614484565b91505f600154905080878381518110612e6e57612e6e614325565b6020026020010151511115612ebd57868281518110612e8f57612e8f614325565b60200260200101515181604051637ae5968560e01b8152600401610754929190918252602082015260400190565b5f805b888481518110612ed257612ed2614325565b602002602001015151811015612fae57888481518110612ef457612ef4614325565b60200260200101518181518110612f0d57612f0d614325565b60200260200101515f1c825f1c10612f6e57888481518110612f3157612f31614325565b60200260200101518181518110612f4a57612f4a614325565b6020026020010151604051636aba776560e11b815260040161075491815260200190565b888481518110612f8057612f80614325565b60200260200101518181518110612f9957612f99614325565b60200260200101519150806001019050612ec0565b505050806001019050612d79565b50803414612ce05760405163312b003360e01b815234600482015260248101829052604401610754565b6040805160038082526080820190925260609182918291602082018380368337019050509250845167ffffffffffffffff81111561302657613026613cba565b60405190808252806020026020018201604052801561305957816020015b60608152602001906001900390816130445790505b509150845167ffffffffffffffff81111561307657613076613cba565b60405190808252806020026020018201604052801561309f578160200160208202803683370190505b5090505f5b8551811015613536575f60085f8884815181106130c3576130c3614325565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f816001600160a01b031663a8b2ae026040518163ffffffff1660e01b8152600401602060405180830381865afa15801561312a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061314e91906142c2565b905086838151811061316257613162614325565b60200260200101515167ffffffffffffffff81111561318357613183613cba565b6040519080825280602002602001820160405280156131ac578160200160208202803683370190505b508584815181106131bf576131bf614325565b60200260200101819052505f5b8784815181106131de576131de614325565b6020026020010151518110156133c5577f000000000000000000000000000000000000000000000000000000000000000088858151811061322157613221614325565b6020026020010151828151811061323a5761323a614325565b60200260200101510361328257604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5f805f806132dd8e8e8a8151811061329c5761329c614325565b60200260200101518e8b815181106132b6576132b6614325565b602002602001015188815181106132cf576132cf614325565b602002602001015189611681565b5f8181526006602052604090208290558d519397509195509350915084908b908a90811061330d5761330d614325565b6020026020010151868151811061332657613326614325565b6020026020010181815250508389898151811061334557613345614325565b602002602001018181516133599190614484565b9052508a5184908c905f9061337057613370614325565b602002602001018181516133849190614484565b9052508a5183908c90600290811061339e5761339e614325565b602002602001018181516133b29190614484565b90525050600190930192506131cc915050565b505f8484815181106133d9576133d9614325565b602002602001015111156134e8575f60095f8a86815181106133fd576133fd614325565b602002602001015181526020019081526020015f205490505f8111156134e65784848151811061342f5761342f614325565b602002602001015181106134885784848151811061344f5761344f614325565b60200260200101518161346291906142ed565b90505f85858151811061347757613477614325565b6020026020010181815250506134b6565b8085858151811061349b5761349b614325565b602002602001018181516134af91906142ed565b9052505f90505b8060095f8b87815181106134cc576134cc614325565b602002602001015181526020019081526020015f20819055505b505b8383815181106134fa576134fa614325565b60200260200101518660018151811061351557613515614325565b602002602001018181516135299190614484565b90525050506001016130a4565b5093509350939050565b5f5b8651811015613b4d575f60085f89848151811061356157613561614325565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f84838151811061359e5761359e614325565b60200260200101511115613669577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb828685815181106135ee576135ee614325565b60200260200101516040518363ffffffff1660e01b81526004016136279291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af1158015613643573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136679190614306565b505b5f8088848151811061367d5761367d614325565b60200260200101515167ffffffffffffffff81111561369e5761369e613cba565b6040519080825280602002602001820160405280156136c7578160200160208202803683370190505b5090505f5b8985815181106136de576136de614325565b602002602001015151811015613760575f89868151811061370157613701614325565b6020026020010151828151811061371a5761371a614325565b6020026020010151111561375857600182828151811061373c5761373c614325565b9115156020928302919091019091015261375583614852565b92505b6001016136cc565b50815f0361377057505050613b45565b5f8267ffffffffffffffff81111561378a5761378a613cba565b6040519080825280602002602001820160405280156137b3578160200160208202803683370190505b5090505f8367ffffffffffffffff8111156137d0576137d0613cba565b6040519080825280602002602001820160405280156137f9578160200160208202803683370190505b5090505f805b8c888151811061381157613811614325565b6020026020010151518110156138f55784818151811061383357613833614325565b6020026020010151156138ed578c888151811061385257613852614325565b6020026020010151818151811061386b5761386b614325565b602002602001015184838151811061388557613885614325565b6020026020010181815250508b88815181106138a3576138a3614325565b602002602001015181815181106138bc576138bc614325565b60200260200101518383815181106138d6576138d6614325565b60209081029190910101526138ea82614852565b91505b6001016137ff565b50602461390b600267ffffffffffffffff614780565b61391591906147a6565b67ffffffffffffffff168d888151811061393157613931614325565b602002602001015111613a91575f835167ffffffffffffffff81111561395957613959613cba565b604051908082528060200260200182016040528015613982578160200160208202803683370190505b5090505f5b84518110156139de578481815181106139a2576139a2614325565b60200260200101515f1c8282815181106139be576139be614325565b6001600160a01b0390921660209283029190910190910152600101613987565b50866001600160a01b031663bde526618a8a81518110613a0057613a00614325565b602002602001015183868f8d81518110613a1c57613a1c614325565b60200260200101518f8e81518110613a3657613a36614325565b60200260200101516040518663ffffffff1660e01b8152600401613a5d949392919061486a565b5f604051808303818588803b158015613a74575f80fd5b505af1158015613a86573d5f803e3d5ffd5b505050505050613b3e565b856001600160a01b03166355442b59898981518110613ab257613ab2614325565b602002602001015185858e8c81518110613ace57613ace614325565b60200260200101518e8d81518110613ae857613ae8614325565b60200260200101516040518663ffffffff1660e01b8152600401613b0f94939291906148b4565b5f604051808303818588803b158015613b26575f80fd5b505af1158015613b38573d5f803e3d5ffd5b50505050505b5050505050505b600101613542565b50505050505050565b5f805f60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ba9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613bcd9190614497565b5f86815260066020526040812054945063ffffffff919091169150839003613c0857604051637c946ed760e01b815260040160405180910390fd5b808303613c3d5782613c1b6001836142ed565b604051637ae5968560e01b815260048101929092526024820152604401610754565b5f858152600760205260409020548015801590613c5a5750808410155b15613c6b5783613c1b6001836142ed565b613c758585614484565b92505f81118015613c8557508083115b15613c8e578092505b81831115613c9a578192505b50509250929050565b5f60208284031215613cb3575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613cf757613cf7613cba565b604052919050565b5f82601f830112613d0e575f80fd5b813567ffffffffffffffff811115613d2857613d28613cba565b613d3b601f8201601f1916602001613cce565b818152846020838601011115613d4f575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215613d7e575f80fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115613da9575f80fd5b613db587828801613cff565b91505092959194509250565b5f67ffffffffffffffff821115613dda57613dda613cba565b5060051b60200190565b5f82601f830112613df3575f80fd5b81356020613e08613e0383613dc1565b613cce565b8083825260208201915060208460051b870101935086841115613e29575f80fd5b602086015b84811015613e455780358352918301918301613e2e565b509695505050505050565b5f82601f830112613e5f575f80fd5b81356020613e6f613e0383613dc1565b82815260059290921b84018101918181019086841115613e8d575f80fd5b8286015b84811015613e4557803567ffffffffffffffff811115613eaf575f80fd5b613ebd8986838b0101613cff565b845250918301918301613e91565b5f805f805f60a08688031215613edf575f80fd5b8535945067ffffffffffffffff8060208801351115613efc575f80fd5b613f0c8860208901358901613de4565b94508060408801351115613f1e575f80fd5b6040870135870188601f820112613f33575f80fd5b613f40613e038235613dc1565b81358082526020808301929160051b8401018b1015613f5d575f80fd5b602083015b6020843560051b850101811015613ff7578481351115613f80575f80fd5b803584018c603f820112613f92575f80fd5b613fa2613e036020830135613dc1565b602082810135808352908201919060051b83016040018f811115613fc4575f80fd5b6040840193505b80841015613fe6578335835260209384019390920191613fcb565b508552505060209283019201613f62565b5095505050606087013581101561400c575f80fd5b61401c8860608901358901613e50565b9250806080880135111561402e575f80fd5b5061403f8760808801358801613de4565b90509295509295909350565b5f805f6060848603121561405d575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106140a857634e487b7160e01b5f52602160045260245ffd5b91905290565b5f602082840312156140be575f80fd5b8135600481106140cc575f80fd5b9392505050565b5f805f80608085870312156140e6575f80fd5b5050823594602084013594506040840135936060013592509050565b80356001600160a01b0381168114614118575f80fd5b919050565b5f6020828403121561412d575f80fd5b6140cc82614102565b5f8060408385031215614147575f80fd5b50508035926020909101359150565b5f805f60608486031215614168575f80fd5b61417184614102565b925061417f60208501614102565b915061418d60408501614102565b90509250925092565b5f80604083850312156141a7575f80fd5b823567ffffffffffffffff808211156141be575f80fd5b6141ca86838701613de4565b935060208501359150808211156141df575f80fd5b506141ec85828601613de4565b9150509250929050565b5f8060408385031215614207575f80fd5b823567ffffffffffffffff8082111561421e575f80fd5b818501915085601f830112614231575f80fd5b81356020614241613e0383613dc1565b82815260059290921b8401810191818101908984111561425f575f80fd5b948201945b838610156142845761427586614102565b82529482019490820190614264565b965050860135925050808211156141df575f80fd5b805160ff81168114614118575f80fd5b5f602082840312156142b9575f80fd5b6140cc82614299565b5f602082840312156142d2575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115614300576143006142d9565b92915050565b5f60208284031215614316575f80fd5b815180151581146140cc575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f815180845260208085019450602084015f5b838110156143685781518752958201959082019060010161434c565b509495945050505050565b5f82825180855260208086019550808260051b8401018186015f5b848110156143e157858303601f190189528151805180855290850190858501905f5b818110156143cc578351835292870192918701916001016143b0565b5050998501999350509083019060010161438e565b5090979650505050505050565b60c081525f61440060c0830189614339565b6020838203818501528189518084528284019150828160051b850101838c015f5b8381101561444f57601f1987840301855261443d838351614339565b94860194925090850190600101614421565b50508681036040880152614463818c614373565b606088019a909a525050505060808301949094525060a00152509392505050565b80820180821115614300576143006142d9565b5f602082840312156144a7575f80fd5b815163ffffffff811681146140cc575f80fd5b80516bffffffffffffffffffffffff81168114614118575f80fd5b5f608082840312156144e5575f80fd5b6040516080810181811067ffffffffffffffff8211171561450857614508613cba565b604052614514836144ba565b8152614522602084016144ba565b6020820152604083015161ffff8116811461453b575f80fd5b604082015261454c60608401614299565b60608201529392505050565b5f8060408385031215614569575f80fd5b505080516020909101519092909150565b8082028115828204841417614300576143006142d9565b634e487b7160e01b5f52601260045260245ffd5b5f826145b3576145b3614591565b500490565b600181815b808511156145f257815f19048211156145d8576145d86142d9565b808516156145e557918102915b93841c93908002906145bd565b509250929050565b5f8261460857506001614300565b8161461457505f614300565b816001811461462a576002811461463457614650565b6001915050614300565b60ff841115614645576146456142d9565b50506001821b614300565b5060208310610133831016604e8410600b8410161715614673575081810a614300565b61467d83836145b8565b805f1904821115614690576146906142d9565b029392505050565b5f6140cc83836145fa565b6001600160a01b0384168152606060208201525f6146c46060830185614339565b82810360408401526146d68185614339565b9695505050505050565b848152836020820152608060408201525f6146fe6080830185614339565b82810360608401526147108185614339565b979650505050505050565b5f815180845260208085019450602084015f5b838110156143685781516001600160a01b03168752958201959082019060010161472e565b604081525f614765604083018561471b565b82810360208401526147778185614339565b95945050505050565b5f67ffffffffffffffff8084168061479a5761479a614591565b92169190910492915050565b67ffffffffffffffff8281168282160390808211156147c7576147c76142d9565b5092915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152836020820152608060408201525f61482360808301856147ce565b905082606083015295945050505050565b848152836020820152608060408201525f61482360808301856147ce565b5f60018201614863576148636142d9565b5060010190565b608081525f61487c608083018761471b565b828103602084015261488e8187614339565b905082810360408401526148a281866147ce565b91505082606083015295945050505050565b608081525f61487c608083018761433956fea26469706673582212204f62b365dfacc16118c8e0397d13c78fb01e19f895ea8e406a87973c6c961c4c64736f6c63430008190033",
"linkReferences": {},
"deployedLinkReferences": {}
}
diff --git a/audits/README.md b/audits/README.md
index 6c263fec..85dc3e82 100644
--- a/audits/README.md
+++ b/audits/README.md
@@ -10,7 +10,9 @@ An internal audit with a focus on depository implementation v.1.0.1 is located i
An internal audit with a focus on PoAA Staking is located in this folder: [internal audit 4](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal4).
-An internal audit with a focus on AIP-1 (bonding) is located in this folder: [internal audit 5](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5).
+An internal audit with a focus on PoAA Staking fixing after C4A is located in this folder: [internal audit 5](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5).
+
+An internal audit with a focus on AIP-1 (bonding) is located in this folder: [internal audit 6](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal6).
### External audit
Audit reports: [v1](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/Autonolas%20Tokenomics%20Smart%20Contract%20Audit.pdf) and [v2](https://sourcehat.com/audits/AutonolasTokenomics/).
diff --git a/audits/internal5/README.md b/audits/internal5/README.md
index d0b56f3f..b9cafd51 100644
--- a/audits/internal5/README.md
+++ b/audits/internal5/README.md
@@ -1,61 +1,130 @@
# Internal audit of autonolas-tokenomics
The review has been performed based on the contract code in the following repository:
`https://github.com/valory-xyz/autonolas-tokenomics`
-commit: `12101b49a2dcdc7a7378f416ddb1611e10459b67` or `tag: v1.3.0-pre-internal-audit`
+commit: `357539f11e3386c18bc9370d4cd20066c7fc0599` or `tag: v1.2.2-pre-internal-audit`
## Objectives
-The audit focused on contracts related to AIP-1 implementation (Bonding) in this repo.
+The audit focused on fixing contracts related to PoAA Staking after C4A.
-### Flatten version
-Flatten version of contracts. [contracts](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5/analysis/contracts)
+### Coverage
+Hardhat coverage has been performed before the audit and can be found here:
+```sh
+---------------------------------|----------|----------|----------|----------|----------------|
+File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |
+---------------------------------|----------|----------|----------|----------|----------------|
+ contracts/ | 99.64 | 96.79 | 100 | 98.09 | |
-### Coverage: N/A
-In this commit, the tests are in the process of being reworked and therefore the coverage section does not make sense.
+ Dispenser.sol | 98.94 | 90.65 | 100 | 93.86 |... 0,1188,1246 |
-### Storage and proxy
-Using sol2uml tools: https://github.com/naddison36/sol2uml
+ contracts/staking/ | 97.52 | 90.83 | 98.36 | 93.97 | |
+ ArbitrumDepositProcessorL1.sol | 100 | 96.15 | 100 | 97.14 | 157 |
+ ArbitrumTargetDispenserL2.sol | 100 | 100 | 100 | 100 | |
+ DefaultDepositProcessorL1.sol | 100 | 90.63 | 100 | 94.83 | 134,227,235 |
+ DefaultTargetDispenserL2.sol | 97.5 | 87.8 | 100 | 92.52 |... 459,489,511 |
+ EthereumDepositProcessor.sol | 85.71 | 88.89 | 100 | 86.11 |... 109,112,114 |
+ GnosisDepositProcessorL1.sol | 100 | 100 | 100 | 100 | |
+ GnosisTargetDispenserL2.sol | 100 | 100 | 100 | 100 | |
+ OptimismDepositProcessorL1.sol | 100 | 100 | 100 | 100 | |
+ OptimismTargetDispenserL2.sol | 100 | 100 | 100 | 100 | |
+ PolygonDepositProcessorL1.sol | 91.67 | 80 | 80 | 84.21 | 97,105,110 |
+ PolygonTargetDispenserL2.sol | 100 | 50 | 100 | 81.82 | 68,73 |
+ WormholeDepositProcessorL1.sol | 100 | 100 | 100 | 100 | |
+ WormholeTargetDispenserL2.sol | 100 | 91.67 | 100 | 96.77 | 114 |
+
+---------------------------------|----------|----------|----------|----------|----------------|
```
-npm link sol2uml --only=production
-sol2uml storage contracts/ -f png -c Tokenomics -o audits/internal4/analysis/storage
-Generated png file audits/internal5/analysis/storage/Tokenomics.png
-```
-[Tokenomics-storage](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5/analysis/storage/Tokenomics.png)
-current deployed:
-[Tokenomics-storage-current](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal4/analysis/storage/Tokenomics.png)
-The new slot allocation for Tokenomics (critical as proxy pattern) does not affect the previous one.
-
-### Security issues.
-#### Problems found instrumentally
-Several checks are obtained automatically. They are commented. Some issues found need to be fixed.
-All automatic warnings are listed in the following file, concerns of which we address in more detail below:
-[slither-full](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5/analysis/slither_full.txt)
-
-#### Issue
-1. minOLASLeftoverAmount never setupped/updated
-```
- // Minimum amount of supply such that any value below is given to the bonding account in order to close the product
- uint256 public minOLASLeftoverAmount;
-```
-2. Reentrancy after ERC721 "safe" mint in deposit
+Please, pay attention.
+[x] Noted. Missing 100% is not an obvious problem.
+
+#### Checking the corrections made after C4A
+##### Bridging
+67. Withheld tokens could become unsynchronized by using retry-ability of bridging protocols #67
+https://github.com/code-423n4/2024-05-olas-findings/issues/67
+[x] fixed
+
+54. OptimismTargetDispenserL2:syncWithheldTokens is callable with no sanity check on payloads and can lead to permanent loss of withheld token amounts #54
+https://github.com/code-423n4/2024-05-olas-findings/issues/54
+20. Users will lose all ETH sent as cost parameter in transactions to and from Optimism #20
+https://github.com/code-423n4/2024-05-olas-findings/issues/20
+4. The msg.value - cost for multiple cross-chain bridges are not refunded to users #4
+https://github.com/code-423n4/2024-05-olas-findings/issues/4
+[x] fixed
+
+32. Refunds for unconsumed gas will be lost due to incorrect refund chain ID #32
+https://github.com/code-423n4/2024-05-olas-findings/issues/32
+[x] fixed
+
+29. Attacker can cancel claimed staking incentives on Arbitrum #29
+https://github.com/code-423n4/2024-05-olas-findings/issues/29
+[x] fixed
+
+26. Non-normalized amounts sent via Wormhole lead to failure to redeem incentives #26
+https://github.com/code-423n4/2024-05-olas-findings/issues/26
+[x] fixed
+
+22. Arbitrary tokens and data can be bridged to GnosisTargetDispenserL2 to manipulate staking incentives #22
+https://github.com/code-423n4/2024-05-olas-findings/issues/22
+[x] fixed
+
+5. The refundAccount is erroneously set to msg.sender instead of tx.origin when refundAccount specified as address(0) #5
+https://github.com/code-423n4/2024-05-olas-findings/issues/5
+[x] fixed
+
+##### Dispenser
+61. Loss of incentives if total weight in an epoch is zero #61
+https://github.com/code-423n4/2024-05-olas-findings/issues/61
+[x] fixed
+
+56. In retain function checkpoint nominee function is not called which can cause zero amount of tokens being retained. #56
+https://github.com/code-423n4/2024-05-olas-findings/issues/56
+[x] fixed
+
+38. Removed nominee doesn't receive staking incentives for the epoch in which they were removed which is against the intended behaviour #38
+https://github.com/code-423n4/2024-05-olas-findings/issues/38
+[x] fixed
+
+27. Unauthorized claiming of staking incentives for retainer #27
+https://github.com/code-423n4/2024-05-olas-findings/issues/27
+[x] fixed
+
+##### No need to change the code, just add information to the documentation
+59. Changing VoteWeighting contract can result in lost staking incentives #59
+https://github.com/code-423n4/2024-05-olas-findings/issues/59
+[x] fixed
+
+#### Low issue
+107. QA Report #107
+https://github.com/code-423n4/2024-05-olas-findings/issues/107
```
- External calls:
- - _safeMint(msg.sender,bondId) (Depository-flatten.sol#891)
- - require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) (Depository-flatten.sol#461-465)
- After adding _safeMint(msg.sender, bondId), it became clearly susceptible reentrancy attack.
- We need to add explicit protection against reentrancy.
+[N-44] Missing event for critical changes addNomenee in Dispenser
```
-#### Genaral notes: more tests need to be done, needed re-audit later
+[x] fixed
+
+110. QA Report #110
+https://github.com/code-423n4/2024-05-olas-findings/issues/110
```
-trackServiceDonations requires a large number of tests and coverage of all scenarios.
+[NonCritical-9] Missing events in sensitive function setL2TargetDispenser(address l2Dispenser)
```
-#### Notes for discussion: epsilonRate
+[x] fixed
+
+113. QA Report #113
+https://github.com/code-423n4/2024-05-olas-findings/issues/113
```
-in this implementation epsilonRate is deprecated and simply not used. perhaps it makes sense (?) to use this dimensionless coefficient as a limiter.
-// The IDF depends on the epsilonRate value, idf = 1 + epsilonRate, and epsilonRate is bound by 17 with 18 decimals
-new
-// IDF = 1 + normalized booster
-idf = 1e18 + discountBooster;
-maybe idf = min(1e18 + discountBooster, 1e18 + epsilonRate)
-Moreover, according to calculations discountBooster <= 1e18 << max(epsilonRate)
+[L-08] Use abi.encodeCall() instead of abi.encodeWithSignature()/abi.encodeWithSelector()
+grep -r encodeWithSelec ./contracts/
+./contracts/staking/OptimismDepositProcessorL1.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(targets, stakingIncentives, batchHash));
+./contracts/staking/OptimismTargetDispenserL2.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(amount, batchHash));
+./contracts/staking/ArbitrumTargetDispenserL2.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(amount, batchHash));
+./contracts/staking/GnosisTargetDispenserL2.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(amount, batchHash));
+./contracts/staking/ArbitrumDepositProcessorL1.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(targets, stakingIncentives, batchHash));
+./contracts/staking/GnosisDepositProcessorL1.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(targets, stakingIncentives, batchHash));
```
+[x] Noted. The fact that codebase hasn't been changed is not a problem.
+
+### Catch up on changes. 15.07.24
+https://github.com/valory-xyz/autonolas-tokenomics/compare/v1.2.2-pre-internal-audit...v1.2.2-pre-audit
+The changes to the codebase appear to be correct.
+
+
+
diff --git a/audits/internal6/README.md b/audits/internal6/README.md
new file mode 100644
index 00000000..db892c93
--- /dev/null
+++ b/audits/internal6/README.md
@@ -0,0 +1,100 @@
+# Internal audit of autonolas-tokenomics
+The review has been performed based on the contract code in the following repository:
+`https://github.com/valory-xyz/autonolas-tokenomics`
+commit: `12101b49a2dcdc7a7378f416ddb1611e10459b67` or `tag: v1.3.0-pre-internal-audit`
+
+## Objectives
+The audit focused on contracts related to AIP-1 implementation (Bonding) in this repo.
+
+### Flatten version
+Flatten version of contracts. [contracts](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5/analysis/contracts)
+
+### Coverage: N/A
+In this commit, the tests are in the process of being reworked and therefore the coverage section does not make sense.
+
+### Storage and proxy
+Using sol2uml tools: https://github.com/naddison36/sol2uml
+```
+npm link sol2uml --only=production
+sol2uml storage contracts/ -f png -c Tokenomics -o audits/internal4/analysis/storage
+Generated png file audits/internal5/analysis/storage/Tokenomics.png
+```
+[Tokenomics-storage](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5/analysis/storage/Tokenomics.png)
+current deployed:
+[Tokenomics-storage-current](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal4/analysis/storage/Tokenomics.png)
+The new slot allocation for Tokenomics (critical as proxy pattern) does not affect the previous one.
+
+### Security issues.
+#### Problems found instrumentally
+Several checks are obtained automatically. They are commented. Some issues found need to be fixed.
+All automatic warnings are listed in the following file, concerns of which we address in more detail below:
+[slither-full](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5/analysis/slither_full.txt)
+
+#### Issue
+1. minOLASLeftoverAmount never setupped/updated
+```
+ // Minimum amount of supply such that any value below is given to the bonding account in order to close the product
+ uint256 public minOLASLeftoverAmount;
+```
+[x] fixed
+
+2. Reentrancy after ERC721 "safe" mint in deposit
+```
+ External calls:
+ - _safeMint(msg.sender,bondId) (Depository-flatten.sol#891)
+ - require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) (Depository-flatten.sol#461-465)
+ After adding _safeMint(msg.sender, bondId), it became clearly susceptible reentrancy attack.
+ We need to add explicit protection against reentrancy.
+```
+[x] fixed
+
+#### General notes: more tests need to be done, needed re-audit later
+```
+trackServiceDonations requires a large number of tests and coverage of all scenarios.
+```
+[x] noted
+
+#### Notes for discussion: epsilonRate
+```
+in this implementation epsilonRate is deprecated and simply not used. perhaps it makes sense (?) to use this dimensionless coefficient as a limiter.
+// The IDF depends on the epsilonRate value, idf = 1 + epsilonRate, and epsilonRate is bound by 17 with 18 decimals
+new
+// IDF = 1 + normalized booster
+idf = 1e18 + discountBooster;
+maybe idf = min(1e18 + discountBooster, 1e18 + epsilonRate)
+Moreover, according to calculations discountBooster <= 1e18 << max(epsilonRate)
+```
+[x] IDF is never bigger than 2e18 by design
+
+### Re-audit 02.08.24
+The review has been performed based on the contract code in the following repository:
+`https://github.com/valory-xyz/autonolas-tokenomics`
+commit: `c76a04a64fd450e1a7a34873ea49b6a4b4b0b856` or `tag: v1.3.0-internal-audit2`
+
+### Coverage
+```
+---------------------------------|----------|----------|----------|----------|----------------|
+File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |
+---------------------------------|----------|----------|----------|----------|----------------|
+ contracts/ | 98.83 | 96.45 | 95.51 | 97.79 | |
+ BondCalculator.sol | 97.44 | 98 | 85.71 | 97.22 | 181,299 |
+ Depository.sol | 95.56 | 92.71 | 81.25 | 93.49 |... 605,608,615 |
+ Dispenser.sol | 98.95 | 93.06 | 100 | 96.24 |... 0,1209,1267 |
+---------------------------------|----------|----------|----------|----------|----------------|
+```
+Please, pay attention.
+
+### Storage and proxy
+Using sol2uml tools: https://github.com/naddison36/sol2uml
+```
+npm link sol2uml --only=production
+sol2uml storage contracts/ -f png -c Tokenomics -o audits/internal6/analysis/storage
+Generated png file audits/internal6/analysis/storage/Tokenomics.png
+```
+[Tokenomics-storage](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal6/analysis/storage/Tokenomics.png)
+current deployed:
+[Tokenomics-storage-current](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal4/analysis/storage/Tokenomics.png)
+The new slot allocation for Tokenomics (critical as proxy pattern) does not affect the previous one.
+
+### Issue
+I don't see any problems.
diff --git a/audits/internal5/analysis/contracts/BondCalculator-flatten.sol b/audits/internal6/analysis/contracts/BondCalculator-flatten.sol
similarity index 100%
rename from audits/internal5/analysis/contracts/BondCalculator-flatten.sol
rename to audits/internal6/analysis/contracts/BondCalculator-flatten.sol
diff --git a/audits/internal5/analysis/contracts/Depository-flatten.sol b/audits/internal6/analysis/contracts/Depository-flatten.sol
similarity index 100%
rename from audits/internal5/analysis/contracts/Depository-flatten.sol
rename to audits/internal6/analysis/contracts/Depository-flatten.sol
diff --git a/audits/internal5/analysis/contracts/script.sh b/audits/internal6/analysis/contracts/script.sh
similarity index 100%
rename from audits/internal5/analysis/contracts/script.sh
rename to audits/internal6/analysis/contracts/script.sh
diff --git a/audits/internal5/analysis/slither_BondCalculator-flatten.sol.BondCalculator.call-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.BondCalculator.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_BondCalculator-flatten.sol.BondCalculator.call-graph.png
rename to audits/internal6/analysis/slither_BondCalculator-flatten.sol.BondCalculator.call-graph.png
diff --git a/audits/internal5/analysis/slither_BondCalculator-flatten.sol.ITokenomics.call-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.ITokenomics.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_BondCalculator-flatten.sol.ITokenomics.call-graph.png
rename to audits/internal6/analysis/slither_BondCalculator-flatten.sol.ITokenomics.call-graph.png
diff --git a/audits/internal5/analysis/slither_BondCalculator-flatten.sol.IUniswapV2Pair.call-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.IUniswapV2Pair.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_BondCalculator-flatten.sol.IUniswapV2Pair.call-graph.png
rename to audits/internal6/analysis/slither_BondCalculator-flatten.sol.IUniswapV2Pair.call-graph.png
diff --git a/audits/internal5/analysis/slither_BondCalculator-flatten.sol.IVotingEscrow.call-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.IVotingEscrow.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_BondCalculator-flatten.sol.IVotingEscrow.call-graph.png
rename to audits/internal6/analysis/slither_BondCalculator-flatten.sol.IVotingEscrow.call-graph.png
diff --git a/audits/internal5/analysis/slither_BondCalculator-flatten.sol.all_contracts.call-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.all_contracts.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_BondCalculator-flatten.sol.all_contracts.call-graph.png
rename to audits/internal6/analysis/slither_BondCalculator-flatten.sol.all_contracts.call-graph.png
diff --git a/audits/internal5/analysis/slither_BondCalculator-flatten.sol.inheritance-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.inheritance-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_BondCalculator-flatten.sol.inheritance-graph.png
rename to audits/internal6/analysis/slither_BondCalculator-flatten.sol.inheritance-graph.png
diff --git a/audits/internal5/analysis/slither_Depository-flatten.sol.Depository.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.Depository.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_Depository-flatten.sol.Depository.call-graph.png
rename to audits/internal6/analysis/slither_Depository-flatten.sol.Depository.call-graph.png
diff --git a/audits/internal5/analysis/slither_Depository-flatten.sol.ERC721TokenReceiver.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.ERC721TokenReceiver.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_Depository-flatten.sol.ERC721TokenReceiver.call-graph.png
rename to audits/internal6/analysis/slither_Depository-flatten.sol.ERC721TokenReceiver.call-graph.png
diff --git a/audits/internal5/analysis/slither_Depository-flatten.sol.IBondCalculator.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.IBondCalculator.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_Depository-flatten.sol.IBondCalculator.call-graph.png
rename to audits/internal6/analysis/slither_Depository-flatten.sol.IBondCalculator.call-graph.png
diff --git a/audits/internal5/analysis/slither_Depository-flatten.sol.IToken.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.IToken.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_Depository-flatten.sol.IToken.call-graph.png
rename to audits/internal6/analysis/slither_Depository-flatten.sol.IToken.call-graph.png
diff --git a/audits/internal5/analysis/slither_Depository-flatten.sol.ITokenomics.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.ITokenomics.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_Depository-flatten.sol.ITokenomics.call-graph.png
rename to audits/internal6/analysis/slither_Depository-flatten.sol.ITokenomics.call-graph.png
diff --git a/audits/internal5/analysis/slither_Depository-flatten.sol.ITreasury.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.ITreasury.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_Depository-flatten.sol.ITreasury.call-graph.png
rename to audits/internal6/analysis/slither_Depository-flatten.sol.ITreasury.call-graph.png
diff --git a/audits/internal5/analysis/slither_Depository-flatten.sol.all_contracts.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.all_contracts.call-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_Depository-flatten.sol.all_contracts.call-graph.png
rename to audits/internal6/analysis/slither_Depository-flatten.sol.all_contracts.call-graph.png
diff --git a/audits/internal5/analysis/slither_Depository-flatten.sol.inheritance-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.inheritance-graph.png
similarity index 100%
rename from audits/internal5/analysis/slither_Depository-flatten.sol.inheritance-graph.png
rename to audits/internal6/analysis/slither_Depository-flatten.sol.inheritance-graph.png
diff --git a/audits/internal5/analysis/slither_call-graph.txt b/audits/internal6/analysis/slither_call-graph.txt
similarity index 100%
rename from audits/internal5/analysis/slither_call-graph.txt
rename to audits/internal6/analysis/slither_call-graph.txt
diff --git a/audits/internal5/analysis/slither_constructor-calls.txt b/audits/internal6/analysis/slither_constructor-calls.txt
similarity index 100%
rename from audits/internal5/analysis/slither_constructor-calls.txt
rename to audits/internal6/analysis/slither_constructor-calls.txt
diff --git a/audits/internal5/analysis/slither_contract-summary.txt b/audits/internal6/analysis/slither_contract-summary.txt
similarity index 100%
rename from audits/internal5/analysis/slither_contract-summary.txt
rename to audits/internal6/analysis/slither_contract-summary.txt
diff --git a/audits/internal5/analysis/slither_data-dependency.txt b/audits/internal6/analysis/slither_data-dependency.txt
similarity index 100%
rename from audits/internal5/analysis/slither_data-dependency.txt
rename to audits/internal6/analysis/slither_data-dependency.txt
diff --git a/audits/internal5/analysis/slither_full.txt b/audits/internal6/analysis/slither_full.txt
similarity index 100%
rename from audits/internal5/analysis/slither_full.txt
rename to audits/internal6/analysis/slither_full.txt
diff --git a/audits/internal5/analysis/slither_function-summary.txt b/audits/internal6/analysis/slither_function-summary.txt
similarity index 100%
rename from audits/internal5/analysis/slither_function-summary.txt
rename to audits/internal6/analysis/slither_function-summary.txt
diff --git a/audits/internal5/analysis/slither_human-summary.txt b/audits/internal6/analysis/slither_human-summary.txt
similarity index 100%
rename from audits/internal5/analysis/slither_human-summary.txt
rename to audits/internal6/analysis/slither_human-summary.txt
diff --git a/audits/internal5/analysis/slither_inheritance-graph.txt b/audits/internal6/analysis/slither_inheritance-graph.txt
similarity index 100%
rename from audits/internal5/analysis/slither_inheritance-graph.txt
rename to audits/internal6/analysis/slither_inheritance-graph.txt
diff --git a/audits/internal5/analysis/slither_inheritance.txt b/audits/internal6/analysis/slither_inheritance.txt
similarity index 100%
rename from audits/internal5/analysis/slither_inheritance.txt
rename to audits/internal6/analysis/slither_inheritance.txt
diff --git a/audits/internal5/analysis/slither_modifiers.txt b/audits/internal6/analysis/slither_modifiers.txt
similarity index 100%
rename from audits/internal5/analysis/slither_modifiers.txt
rename to audits/internal6/analysis/slither_modifiers.txt
diff --git a/audits/internal5/analysis/slither_require.txt b/audits/internal6/analysis/slither_require.txt
similarity index 100%
rename from audits/internal5/analysis/slither_require.txt
rename to audits/internal6/analysis/slither_require.txt
diff --git a/audits/internal5/analysis/slither_variable-order.txt b/audits/internal6/analysis/slither_variable-order.txt
similarity index 100%
rename from audits/internal5/analysis/slither_variable-order.txt
rename to audits/internal6/analysis/slither_variable-order.txt
diff --git a/audits/internal5/analysis/slither_vars-and-auth.txt b/audits/internal6/analysis/slither_vars-and-auth.txt
similarity index 100%
rename from audits/internal5/analysis/slither_vars-and-auth.txt
rename to audits/internal6/analysis/slither_vars-and-auth.txt
diff --git a/audits/internal5/analysis/storage/Tokenomics.png b/audits/internal6/analysis/storage/Tokenomics.png
similarity index 82%
rename from audits/internal5/analysis/storage/Tokenomics.png
rename to audits/internal6/analysis/storage/Tokenomics.png
index 5e281d85..754e86cd 100644
Binary files a/audits/internal5/analysis/storage/Tokenomics.png and b/audits/internal6/analysis/storage/Tokenomics.png differ
diff --git a/contracts/Depository.sol b/contracts/Depository.sol
index f18559fc..e6a86c9b 100644
--- a/contracts/Depository.sol
+++ b/contracts/Depository.sol
@@ -128,6 +128,8 @@ contract Depository is ERC721, IErrorsTokenomics {
address public treasury;
// Bond Calculator contract address
address public bondCalculator;
+ // Reentrancy lock
+ uint8 internal _locked;
// Mapping of bond Id => account bond instance
mapping(uint256 => Bond) public mapUserBonds;
@@ -225,6 +227,17 @@ contract Depository is ERC721, IErrorsTokenomics {
}
}
+ /// @dev Sets minimum OLAS leftover amount for the product to keep the supply.
+ /// @param _minOLASLeftoverAmount Updated minimum OLAS leftover amount.
+ function setMinOLASLeftoverAmount(uint256 _minOLASLeftoverAmount) external {
+ // Check for the contract ownership
+ if (msg.sender != owner) {
+ revert OwnerOnly(msg.sender, owner);
+ }
+
+ minOLASLeftoverAmount = _minOLASLeftoverAmount;
+ }
+
/// @dev Creates a new bond product.
/// @param token LP token to be deposited for pairs like OLAS-DAI, OLAS-ETH, etc.
/// @param priceLP LP token price with 18 additional decimals.
@@ -344,6 +357,12 @@ contract Depository is ERC721, IErrorsTokenomics {
function deposit(uint256 productId, uint256 tokenAmount, uint256 bondVestingTime) external
returns (uint256 payout, uint256 maturity, uint256 bondId)
{
+ // Reentrancy guard
+ if (_locked > 1) {
+ revert ReentrancyGuard();
+ }
+ _locked = 2;
+
// Check the token amount
if (tokenAmount == 0) {
revert ZeroValue();
@@ -423,6 +442,8 @@ contract Depository is ERC721, IErrorsTokenomics {
}
emit CreateBond(token, productId, msg.sender, bondId, payout, tokenAmount, maturity);
+
+ _locked = 1;
}
/// @dev Redeems account bonds.
diff --git a/contracts/Dispenser.sol b/contracts/Dispenser.sol
index 6b10797e..8d869a2f 100644
--- a/contracts/Dispenser.sol
+++ b/contracts/Dispenser.sol
@@ -267,13 +267,18 @@ contract Dispenser {
event TreasuryUpdated(address indexed treasury);
event VoteWeightingUpdated(address indexed voteWeighting);
event StakingParamsUpdated(uint256 maxNumClaimingEpochs, uint256 maxNumStakingTargets);
- event IncentivesClaimed(address indexed owner, uint256 reward, uint256 topUp);
- event StakingIncentivesClaimed(address indexed account, uint256 stakingIncentive, uint256 transferAmount,
- uint256 returnAmount);
+ event IncentivesClaimed(address indexed owner, uint256 reward, uint256 topUp, uint256[] unitTypes, uint256[] unitIds);
+ event StakingIncentivesClaimed(address indexed account, uint256 chainId, bytes32 stakingTarget,
+ uint256 stakingIncentive, uint256 transferAmount, uint256 returnAmount);
+ event StakingIncentivesBatchClaimed(address indexed account, uint256[] chainIds, bytes32[][] stakingTargets,
+ uint256[][] stakingIncentives, uint256 totalStakingIncentive, uint256 totalTransferAmount,
+ uint256 totalReturnAmount);
event Retained(address indexed account, uint256 returnAmount);
event SetDepositProcessorChainIds(address[] depositProcessors, uint256[] chainIds);
event WithheldAmountSynced(uint256 chainId, uint256 amount, uint256 updatedWithheldAmount, bytes32 indexed batchHash);
event PauseDispenser(Pause pauseState);
+ event AddNomineeHash(bytes32 indexed nomineeHash);
+ event RemoveNomineeHash(bytes32 indexed nomineeHash);
// Maximum chain Id as per EVM specs
uint256 public constant MAX_EVM_CHAIN_ID = type(uint64).max / 2 - 36;
@@ -397,11 +402,11 @@ contract Dispenser {
revert Overflow(firstClaimedEpoch, eCounter - 1);
}
- // Get epoch when the nominee was removed
+ // Get epoch number when the nominee was removed
uint256 epochRemoved = mapRemovedNomineeEpochs[nomineeHash];
- // If the nominee is not removed, its value in the map is always zero, unless removed
+ // If the nominee is not removed, its value in the map is always zero
// The staking contract nominee cannot be removed in the zero-th epoch by default
- if (epochRemoved > 1 && firstClaimedEpoch >= epochRemoved) {
+ if (epochRemoved > 0 && firstClaimedEpoch >= epochRemoved) {
revert Overflow(firstClaimedEpoch, epochRemoved - 1);
}
@@ -410,7 +415,7 @@ contract Dispenser {
// Limit last claimed epoch by the number following the nominee removal epoch
// The condition for is lastClaimedEpoch strictly > because the lastClaimedEpoch is not included in claiming
- if (epochRemoved > 1 && lastClaimedEpoch > epochRemoved) {
+ if (epochRemoved > 0 && lastClaimedEpoch > epochRemoved) {
lastClaimedEpoch = epochRemoved;
}
@@ -487,6 +492,11 @@ contract Dispenser {
}
}
+ // Skip if there are no actual staking targets
+ if (numActualTargets == 0) {
+ continue;
+ }
+
// Allocate updated arrays accounting only for nonzero staking incentives
bytes32[] memory updatedStakingTargets = new bytes32[](numActualTargets);
uint256[] memory updatedStakingAmounts = new uint256[](numActualTargets);
@@ -769,9 +779,17 @@ contract Dispenser {
}
mapLastClaimedStakingEpochs[nomineeHash] = ITokenomics(tokenomics).epochCounter();
+
+ emit AddNomineeHash(nomineeHash);
}
/// @dev Records nominee removal epoch number.
+ /// @notice The staking contract nominee cannot be removed starting from one week before the end of epoch.
+ /// Since the epoch end time is unknown and the nominee removal is applied in the following week,
+ /// it is prohibited to remove nominee one week before the foreseen epoch end to correctly reflect
+ /// the removal epoch number.
+ /// If the staking contract nominee must not get incentives in the ongoing ending epoch as well,
+ /// the DAO is advised to use the removeInstance() function in the corresponding StakingFactory contract.
/// @param nomineeHash Nominee hash.
function removeNominee(bytes32 nomineeHash) external {
// Check for the contract ownership
@@ -803,6 +821,8 @@ contract Dispenser {
// Set the removed nominee epoch number
mapRemovedNomineeEpochs[nomineeHash] = eCounter;
+
+ emit RemoveNomineeHash(nomineeHash);
}
/// @dev Claims incentives for the owner of components / agents.
@@ -857,7 +877,7 @@ contract Dispenser {
revert ClaimIncentivesFailed(msg.sender, reward, topUp);
}
- emit IncentivesClaimed(msg.sender, reward, topUp);
+ emit IncentivesClaimed(msg.sender, reward, topUp, unitTypes, unitIds);
_locked = 1;
}
@@ -1097,7 +1117,7 @@ contract Dispenser {
_distributeStakingIncentives(chainId, stakingTarget, stakingIncentive, bridgePayload, transferAmount);
}
- emit StakingIncentivesClaimed(msg.sender, stakingIncentive, transferAmount, returnAmount);
+ emit StakingIncentivesClaimed(msg.sender, chainId, stakingTarget, stakingIncentive, transferAmount, returnAmount);
_locked = 1;
}
@@ -1176,7 +1196,8 @@ contract Dispenser {
valueAmounts);
}
- emit StakingIncentivesClaimed(msg.sender, totalAmounts[0], totalAmounts[1], totalAmounts[2]);
+ emit StakingIncentivesBatchClaimed(msg.sender, chainIds, stakingTargets, stakingIncentives, totalAmounts[0],
+ totalAmounts[1], totalAmounts[2]);
_locked = 1;
}
diff --git a/contracts/Tokenomics.sol b/contracts/Tokenomics.sol
index ea4704ba..98581e8c 100644
--- a/contracts/Tokenomics.sol
+++ b/contracts/Tokenomics.sol
@@ -247,11 +247,16 @@ struct StakingPoint {
uint8 stakingFraction;
}
-// Struct for service staking epoch info
+// Struct for donation point
struct DonationPoint {
+ // Amount of OLAS intended to fund component / agent top-ups for the epoch based on the inflation schedule
+ // After 10 years, the OLAS inflation rate is 2% per year. It would take 220+ years to reach 2^96 - 1
uint96 totalUnitTopUps;
+ // Amount of veOLAS power used to trigger top-ups accumulated from all the unique donators per a single epoch
+ // veOLAS amount cannot practically be bigger than the OLAS amount
uint96 totalDonationPower;
- bool moreDonationPower;
+ // Sum of component / agent top-up fractions in a corresponding epoch
+ uint8 sumTopUpUnitFractions;
}
/// @title Tokenomics - Smart contract for tokenomics logic with incentives for unit owners, discount factor
@@ -381,9 +386,9 @@ contract Tokenomics is TokenomicsConstants {
// Mapping of epoch => service staking point
mapping(uint256 => StakingPoint) public mapEpochStakingPoints;
// Mapping of hash(epoch + donator address) => true the voting power has been utilized in the on-going epoch
- mapping(bytes32 => bool) public mapEpochDonatorPowerHashes;
+ mapping(bytes32 => bool) public mapEpochDonationPowerHashes;
// Mapping of epoch => donation point
- mapping(uint256 => DonationPoint) mapDonationPoints;
+ mapping(uint256 => DonationPoint) public mapDonationPoints;
/// @dev Tokenomics constructor.
constructor()
@@ -864,19 +869,20 @@ contract Tokenomics is TokenomicsConstants {
// The pendingRelativeTopUp can be zero if the service owner did not stake enough veOLAS
// The topUpUnitFraction was checked before and if it were zero, pendingRelativeTopUp would be zero as well
if (totalIncentives > 0) {
+ DonationPoint memory donationPoint = mapDonationPoints[epochNum];
// Summation of all the unit top-ups and total amount of top-ups per epoch
- // TODO: update the formula
- // topUp = (pendingRelativeTopUp * totalTopUpsOLAS * topUpUnitFraction) / (100 * sumUnitTopUpsOLAS)
- if (mapDonationPoints[epochNum].moreDonationPower) {
- // TODO: calculate top-ups for components and agents before this function call, before the loop if possible
- uint256 totalTopUpsOLAS = mapEpochTokenomics[epochNum].epochPoint.totalTopUpsOLAS;
- // TODO: pass this as a function parameter in order to optimize on gas
- uint256 totalDonationPower = mapDonationPoints[epochNum].totalDonationPower;
- totalIncentives *= totalTopUpsOLAS * mapEpochTokenomics[epochNum].unitPoints[unitType].topUpUnitFraction;
- totalIncentives = mapUnitIncentives[unitType][unitId].topUp + (totalIncentives / (totalDonationPower * 100));
+ // topUp = (pendingRelativeTopUp * totalUnitTopUps * topUpUnitFraction) / sumTopUpUnitFractions, if totalDonationPower > totalUnitTopUps
+ // topUp = pendingRelativeTopUp * topUpUnitFraction, otherwise
+ totalIncentives *= mapEpochTokenomics[epochNum].unitPoints[unitType].topUpUnitFraction;
+ if (donationPoint.totalDonationPower > donationPoint.totalUnitTopUps) {
+ totalIncentives = mapUnitIncentives[unitType][unitId].topUp +
+ (totalIncentives * donationPoint.totalUnitTopUps) /
+ (donationPoint.totalDonationPower * donationPoint.sumTopUpUnitFractions);
} else {
- totalIncentives = mapUnitIncentives[unitType][unitId].topUp + totalIncentives;
+ totalIncentives = mapUnitIncentives[unitType][unitId].topUp +
+ totalIncentives / donationPoint.sumTopUpUnitFractions;
}
+ // Record the accumulated top-up value
mapUnitIncentives[unitType][unitId].topUp = uint96(totalIncentives);
// Setting pending top-up to zero
mapUnitIncentives[unitType][unitId].pendingRelativeTopUp = 0;
@@ -914,9 +920,9 @@ contract Tokenomics is TokenomicsConstants {
uint256 vPower;
if (incentiveFlags[2] || incentiveFlags[3]) {
vPower = IVotingEscrow(ve).getVotes(donator);
- bytes32 donatorPowerHash = keccak256(abi.encode(epochCounter, donator));
+ bytes32 donationPowerHash = keccak256(abi.encode(epochCounter, donator));
// Check the donator voting power
- if (vPower < veOLASThreshold || mapEpochDonatorPowerHashes[donatorPowerHash]) {
+ if (vPower < veOLASThreshold || mapEpochDonationPowerHashes[donationPowerHash]) {
// If voting power is below the threshold or has been already utilized during the on-going epoch,
// top-ups are not eligible
vPower = 0;
@@ -926,7 +932,7 @@ contract Tokenomics is TokenomicsConstants {
// Otherwise, split them to the corresponding number of services
vPower /= numServices;
// Add donator voting power to the map
- mapEpochDonatorPowerHashes[donatorPowerHash] = true;
+ mapEpochDonationPowerHashes[donationPowerHash] = true;
}
}
@@ -1206,11 +1212,11 @@ contract Tokenomics is TokenomicsConstants {
// we still record the amount of OLAS allocated for component / agent owner top-ups from the inflation schedule.
// This amount will appear in the EpochSettled event, and thus can be tracked historically
uint256 accountTopUps = incentives[5] + incentives[6];
- // Record donation power state in a settled epoch
- if (mapDonationPoints[eCounter].totalDonationPower > accountTopUps) {
- mapDonationPoints[eCounter].moreDonationPower = true;
- }
- mapDonationPoints[eCounter].totalDonationPower = uint96(accountTopUps);
+
+ // Record total unit top-ups and fractions in a settled epoch
+ mapDonationPoints[eCounter].totalUnitTopUps = uint96(accountTopUps);
+ mapDonationPoints[eCounter].sumTopUpUnitFractions = tp.unitPoints[0].topUpUnitFraction +
+ tp.unitPoints[1].topUpUnitFraction;
// Service staking funding
// Refunded amount during the epoch
@@ -1413,19 +1419,16 @@ contract Tokenomics is TokenomicsConstants {
// Add the final top-up for the last epoch
totalIncentives = mapUnitIncentives[unitTypes[i]][unitIds[i]].pendingRelativeTopUp;
if (totalIncentives > 0) {
+ DonationPoint memory donationPoint = mapDonationPoints[lastEpoch];
// Summation of all the unit top-ups and total amount of top-ups per epoch
- // TODO: update the formula
- // topUp = (pendingRelativeTopUp * totalTopUpsOLAS * topUpUnitFraction) / (100 * sumUnitTopUpsOLAS)
- // Accumulate to the final top-up for the last epoch
- if (mapDonationPoints[lastEpoch].moreDonationPower) {
- // TODO: calculate top-ups for components and agents before this function call, before the loop if possible
- uint256 totalTopUpsOLAS = mapEpochTokenomics[lastEpoch].epochPoint.totalTopUpsOLAS;
- // TODO: pass this as a function parameter in order to optimize on gas
- uint256 totalDonationPower = mapDonationPoints[lastEpoch].totalDonationPower;
- totalIncentives *= totalTopUpsOLAS * mapEpochTokenomics[lastEpoch].unitPoints[unitTypes[i]].topUpUnitFraction;
- totalIncentives = mapUnitIncentives[unitTypes[i]][unitIds[i]].topUp + (totalIncentives / (totalDonationPower * 100));
+ // topUp = (pendingRelativeTopUp * totalUnitTopUps * topUpUnitFraction) / sumTopUpUnitFractions, if totalDonationPower > totalUnitTopUps
+ // topUp = pendingRelativeTopUp * topUpUnitFraction, otherwise
+ totalIncentives *= mapEpochTokenomics[lastEpoch].unitPoints[unitTypes[i]].topUpUnitFraction;
+ if (donationPoint.totalDonationPower > donationPoint.totalUnitTopUps) {
+ topUp += (totalIncentives * donationPoint.totalUnitTopUps) /
+ (donationPoint.totalDonationPower * donationPoint.sumTopUpUnitFractions);
} else {
- topUp += totalIncentives;
+ topUp += totalIncentives / donationPoint.sumTopUpUnitFractions;
}
}
}
diff --git a/contracts/test/ReentrancyAttacker.sol b/contracts/test/ReentrancyAttacker.sol
index 938f5f13..ebadb4a4 100644
--- a/contracts/test/ReentrancyAttacker.sol
+++ b/contracts/test/ReentrancyAttacker.sol
@@ -58,6 +58,10 @@ contract ReentrancyAttacker {
attackMode = _attackMode;
}
+ /// @dev Makes a deposit from an attacker in order to get top-ups from the inflation
+ function depositServiceDonationsETH(uint256[] memory serviceIds, uint256[] memory amounts) external payable {
+ ITokenomics(treasury).depositServiceDonationsETH{value: msg.value}(serviceIds, amounts);
+ }
/// @dev Lets the attacker call back its contract to get back to the claimOwnerIncentives() function.
function badClaimOwnerIncentives(bool attack, uint256[] memory unitTypes, uint256[] memory unitIds) external
diff --git a/docs/configuration.json b/docs/configuration.json
index d6afd484..eca1c39c 100644
--- a/docs/configuration.json
+++ b/docs/configuration.json
@@ -10,8 +10,8 @@
},
{
"name": "Tokenomics",
- "artifact": "abis/0.8.20/Tokenomics.json",
- "address": "0xD599ED4a5c45Fa66AA3C474b00701Fd452a2C30e"
+ "artifact": "abis/0.8.25/Tokenomics.json",
+ "address": "0x2C1633765c66a7CF0EC801a1046347bBee7344C9"
},
{
"name": "TokenomicsProxy",
@@ -30,54 +30,180 @@
},
{
"name": "Dispenser",
- "artifact": "abis/0.8.18/Dispenser.json",
- "address": "0xeED0000fE94d7cfeF4Dc0CA86a223f0F603A61B8"
+ "artifact": "abis/0.8.25/Dispenser.json",
+ "address": "0x5650300fCBab43A0D7D02F8Cb5d0f039402593f0"
},
{
"name": "Depository",
"artifact": "abis/0.8.20/Depository.json",
"address": "0xfF8697d8d2998d6AA2e09B405795C6F4BEeB0C81"
- }
- ]
- },
- {
- "name": "goerli",
- "chainId": "5",
- "contracts": [
+ },
{
- "name": "DonatorBlacklist",
- "artifact": "abis/0.8.18/DonatorBlacklist.json",
- "address": "0x1E11f1224e32Fe0f65FF7D13aD4b053B83bD09FA"
+ "name": "ArbitrumDepositProcessorL1",
+ "artifact": "abis/0.8.25/ArbitrumDepositProcessorL1.json",
+ "address": "0x5e13E07006D68B097DCb5979ef5545C4f9156162"
},
{
- "name": "Tokenomics",
- "artifact": "abis/0.8.20/Tokenomics.json",
- "address": "0x93Cd3f6DcE64d67f4420939865A00aC89776D4b5"
+ "name": "OptimismDepositProcessorL1",
+ "artifact": "abis/0.8.25/OptimismDepositProcessorL1.json",
+ "address": "0x42BA1BbD797E4C90F386F03a544F3b62C1f917d0"
},
{
- "name": "TokenomicsProxy",
- "artifact": "abis/0.8.18/TokenomicsProxy.json",
- "address": "0x10100e74b7F706222F8A7C0be9FC7Ae1717Ad8B2"
+ "name": "WormholeDepositProcessorL1",
+ "artifact": "abis/0.8.25/WormholeDepositProcessorL1.json",
+ "address": "0x223902b6C583f18E8dc84AF4E6a8fa523d088B78"
},
{
- "name": "Treasury",
- "artifact": "abis/0.8.18/Treasury.json",
- "address": "0x7bedCA17D29e53C8062d10902a6219F8d1E3B9B5"
+ "name": "EthereumDepositProcessor",
+ "artifact": "abis/0.8.25/EthereumDepositProcessor.json",
+ "address": "0x15CD7fAeE048c7673aB818C9e582630F1a924593"
},
{
- "name": "GenericBondCalculator",
- "artifact": "abis/0.8.18/GenericBondCalculator.json",
- "address": "0x77290FF625fc576f465D0256F6a12Ce4480a5b8a"
+ "name": "GnosisDepositProcessorL1",
+ "artifact": "abis/0.8.25/GnosisDepositProcessorL1.json",
+ "address": "0xEEf2c02cFC445bFFf1c891D486424Ef3aBc66AB0"
},
{
- "name": "Dispenser",
- "artifact": "abis/0.8.18/Dispenser.json",
- "address": "0xeDd71796B90eaCc56B074C39BAC90ED2Ca6D93Ee"
+ "name": "OptimismDepositProcessorL1",
+ "artifact": "abis/0.8.25/OptimismDepositProcessorL1.json",
+ "address": "0xAB787ceebe8F2b8dca44e3bB744D6e63003ee978"
},
{
- "name": "Depository",
- "artifact": "abis/0.8.20/Depository.json",
- "address": "0x5FDc466f4A7547c876eF40CD30fFA2A89F1EcDE7"
+ "name": "PolygonDepositProcessorL1",
+ "artifact": "abis/0.8.25/PolygonDepositProcessorL1.json",
+ "address": "0x4Ce43b82EF1298E1466D3b3Cee67BA6680bF82FB"
+ }
+ ]
+ },
+ {
+ "name": "arbitrumOne",
+ "chainId": "42161",
+ "contracts": [
+ {
+ "name": "ArbitrumTargetDispenserL2",
+ "artifact": "abis/0.8.25/ArbitrumTargetDispenserL2.json",
+ "address": "0x10c5525F77F13b28f42c5626240c001c2D57CAd4"
+ }
+ ]
+ },
+ {
+ "name": "arbitrumSepolia",
+ "chainId": "421614",
+ "contracts": [
+ {
+ "name": "ArbitrumTargetDispenserL2",
+ "artifact": "abis/0.8.25/ArbitrumTargetDispenserL2.json",
+ "address": ""
+ }
+ ]
+ },
+ {
+ "name": "base",
+ "chainId": "8453",
+ "contracts": [
+ {
+ "name": "OptimismTargetDispenserL2",
+ "artifact": "abis/0.8.25/OptimismTargetDispenserL2.json",
+ "address": "0xcDdD9D9ABaB36fFa882530D69c73FeE5D4001C2d"
+ }
+ ]
+ },
+ {
+ "name": "baseSepolia",
+ "chainId": "84532",
+ "contracts": [
+ {
+ "name": "OptimismTargetDispenserL2",
+ "artifact": "abis/0.8.25/OptimismTargetDispenserL2.json",
+ "address": ""
+ }
+ ]
+ },
+ {
+ "name": "celo",
+ "chainId": "42220",
+ "contracts": [
+ {
+ "name": "WormholeTargetDispenserL2",
+ "artifact": "abis/0.8.25/WormholeTargetDispenserL2.json",
+ "address": "0xb4096d181C08DDF75f1A63918cCa0d1023C4e6C7"
+ }
+ ]
+ },
+ {
+ "name": "celoAlfajores",
+ "chainId": "44787",
+ "contracts": [
+ {
+ "name": "WormholeTargetDispenserL2",
+ "artifact": "abis/0.8.25/WormholeTargetDispenserL2.json",
+ "address": ""
+ }
+ ]
+ },
+ {
+ "name": "gnosis",
+ "chainId": "100",
+ "contracts": [
+ {
+ "name": "GnosisTargetDispenserL2",
+ "artifact": "abis/0.8.25/GnosisTargetDispenserL2.json",
+ "address": "0x67722c823010CEb4BED5325fE109196C0f67D053"
+ }
+ ]
+ },
+ {
+ "name": "chiado",
+ "chainId": "10200",
+ "contracts": [
+ {
+ "name": "GnosisTargetDispenserL2",
+ "artifact": "abis/0.8.25/GnosisTargetDispenserL2.json",
+ "address": ""
+ }
+ ]
+ },
+ {
+ "name": "optimistic",
+ "chainId": "10",
+ "contracts": [
+ {
+ "name": "OptimismTargetDispenserL2",
+ "artifact": "abis/0.8.25/OptimismTargetDispenserL2.json",
+ "address": "0x04b0007b2aFb398015B76e5f22993a1fddF83644"
+ }
+ ]
+ },
+ {
+ "name": "optimisticSepolia",
+ "chainId": "11155420",
+ "contracts": [
+ {
+ "name": "OptimismTargetDispenserL2",
+ "artifact": "abis/0.8.25/OptimismTargetDispenserL2.json",
+ "address": ""
+ }
+ ]
+ },
+ {
+ "name": "polygon",
+ "chainId": "137",
+ "contracts": [
+ {
+ "name": "PolygonTargetDispenserL2",
+ "artifact": "abis/0.8.25/PolygonTargetDispenserL2.json",
+ "address": "0xf76953444C35F1FcE2F6CA1b167173357d3F5C17"
+ }
+ ]
+ },
+ {
+ "name": "polygonAmoy",
+ "chainId": "80002",
+ "contracts": [
+ {
+ "name": "PolygonTargetDispenserL2",
+ "artifact": "abis/0.8.25/PolygonTargetDispenserL2.json",
+ "address": ""
}
]
}
diff --git a/docs/deployment_v1.2.md b/docs/deployment_v1.2.md
new file mode 100644
index 00000000..37cbb6ed
--- /dev/null
+++ b/docs/deployment_v1.2.md
@@ -0,0 +1,24 @@
+Steps for deploying the tokenomics version 1.2 contracts are as follows:
+
+1. EOA to deploy Tokenomics implementation (`TokenomicsThree`);
+2. TokenomicsProxy to change Tokenomics implementation calling `changeTokenomicsImplementation(TokenomicsThree)`;
+3. EOA to deploy Dispenser with VoteWeighting contract being deployed before that in `autonolas-governance`;
+4. EOA to change Dispenser address in VoteWeighting calling `changeDispenser(Dispenser)`;
+5. EOA to unpause staking incentives in Dispenser calling `setPauseState(0)`;
+6. EOA to add a retainer address as a nominee in VoteWeighting;
+7. EOA to deploy staking bridging contracts on L1 and L2 with StakingFactory contract being deployed before that in `autonolas-registries`;
+8. EOA to set up correct L1->L2 links for all the bridging contracts calling `setL2TargetDispenser(L2 corresponding contract)`;
+9. EOA to enable bridge deposit processors in Dispenser calling `setDepositProcessorChainIds()`;
+10. EOA to transfer ownership rights of all the L2 bridging contracts to Timelock representation calling `changeOwner(Timelock)`;
+11. EOA to transfer ownership rights of Dispenser to Timelock calling `changeOwner(Timelock)`;
+12. DAO to change Tokenomics managers calling `changeManagers(ZeroAddress, ZeroAddress, Dispenser)`;
+13. DAO to change staking parameters in Tokenomics calling `changeStakingParams()`;
+14. DAO to change Treasury managers calling `changeManagers(ZeroAddress, ZeroAddress, Dispenser)`.
+
+Note for updating VoteWeighting contract address in Dispenser, if required at some point of time.
+As outlined in the C4R [issue 59](https://github.com/code-423n4/2024-05-olas-findings/issues/59), the following set of
+steps must be taken into account in order to avoid possible staking inflation loss:
+- Initiate claim of incentives for all the outstanding staking contract, as those are ownerless;
+- Pause staking incentives;
+- Change VoteWeighting contract;
+- Unpause staking incentives.
\ No newline at end of file
diff --git a/scripts/audit_chains/audit_contracts_setup.js b/scripts/audit_chains/audit_contracts_setup.js
index 4fd2dc98..f4272176 100644
--- a/scripts/audit_chains/audit_contracts_setup.js
+++ b/scripts/audit_chains/audit_contracts_setup.js
@@ -3,6 +3,7 @@
const { ethers } = require("ethers");
const { expect } = require("chai");
const fs = require("fs");
+const AddressZero = ethers.constants.AddressZero;
// Custom expect that is wrapped into try / catch block
function customExpect(arg1, arg2, log) {
@@ -58,10 +59,18 @@ async function checkBytecode(provider, configContracts, contractName, log) {
}
// Find the contract name from the configuration data
-async function findContractInstance(provider, configContracts, contractName) {
+// idx is to choose the contract, if there are more than one
+async function findContractInstance(provider, configContracts, contractName, idx = 0) {
+ let numFound = 0;
// Get the contract number from the set of configuration contracts
for (let i = 0; i < configContracts.length; i++) {
if (configContracts[i]["name"] === contractName) {
+ // Keep searching if needed idx is not found
+ if (numFound != idx) {
+ numFound++;
+ continue;
+ }
+
// Get the contract instance
let contractFromJSON = fs.readFileSync(configContracts[i]["artifact"], "utf8");
@@ -127,7 +136,7 @@ async function checkTokenomicsProxy(chainId, provider, globalsInstance, configCo
const implementationHash = await tokenomics.PROXY_TOKENOMICS();
const implementation = await provider.getStorageAt(tokenomics.address, implementationHash);
// Need to extract address size of bytes from the storage return value
- customExpect("0x" + implementation.slice(-40), globalsInstance["tokenomicsTwoAddress"].toLowerCase(),
+ customExpect("0x" + implementation.slice(-40), globalsInstance["tokenomicsThreeAddress"].toLowerCase(),
log + ", function: PROXY_TOKENOMICS()");
}
@@ -166,7 +175,7 @@ async function checkTreasury(chainId, provider, globalsInstance, configContracts
// Check paused
const paused = await treasury.paused();
- customExpect(paused, false, log + ", function: paused()");
+ customExpect(paused, 1, log + ", function: paused()");
}
// Check Generic Bond Calculator: chain Id, provider, parsed globals, configuration contracts, contract name
@@ -247,10 +256,400 @@ async function checkDepository(chainId, provider, globalsInstance, configContrac
customExpect(minVesting, 3600 * 24, log + ", function: VERSION()");
}
+// Check DepositProcessorL1: contract, globalsInstance
+async function checkDepositProcessorL1(depositProcessorL1, globalsInstance, log) {
+ log += ", address: " + depositProcessorL1.address;
+ // Check contract owner
+ const owner = await depositProcessorL1.owner();
+ customExpect(owner, AddressZero, log + ", function: owner()");
+
+ // Check L1 OLAS token
+ const olas = await depositProcessorL1.olas();
+ customExpect(olas, globalsInstance["olasAddress"], log + ", function: olas()");
+
+ // Check L1 dispenser
+ const dispenser = await depositProcessorL1.l1Dispenser();
+ customExpect(dispenser, globalsInstance["dispenserAddress"], log + ", function: dispenser ()");
+}
+
+// Check ArbitrumDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkArbitrumDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const arbitrumDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + arbitrumDepositProcessorL1.address;
+ await checkDepositProcessorL1(arbitrumDepositProcessorL1, globalsInstance, log);
+
+ // Check L1 token relayer
+ const l1TokenRelayer = await arbitrumDepositProcessorL1.l1TokenRelayer();
+ customExpect(l1TokenRelayer, globalsInstance["arbitrumL1ERC20GatewayRouterAddress"], log + ", function: l1TokenRelayer()");
+
+ // Check L1 message relayer
+ const l1MessageRelayer = await arbitrumDepositProcessorL1.l1MessageRelayer();
+ customExpect(l1MessageRelayer, globalsInstance["arbitrumInboxAddress"], log + ", function: l1MessageRelayer()");
+
+ // Check L2 target chain Id
+ const l2TargetChainId = await arbitrumDepositProcessorL1.l2TargetChainId();
+ customExpect(l2TargetChainId.toString(), globalsInstance["arbitrumL2TargetChainId"], log + ", function: l2TargetChainId()");
+
+ // Check L1 ERC20Gateway
+ const l1ERC20Gateway = await arbitrumDepositProcessorL1.l1ERC20Gateway();
+ customExpect(l1ERC20Gateway, globalsInstance["arbitrumL1ERC20GatewayAddress"], log + ", function: l1ERC20Gateway()");
+
+ // Check L1 outbox
+ const outbox = await arbitrumDepositProcessorL1.outbox();
+ customExpect(outbox, globalsInstance["arbitrumOutboxAddress"], log + ", function: outbox()");
+
+ // Check L1 bridge
+ const bridge = await arbitrumDepositProcessorL1.bridge();
+ customExpect(bridge, globalsInstance["arbitrumBridgeAddress"], log + ", function: bridge()");
+
+ // Check L2 target dispenser
+ const l2TargetDispenser = await arbitrumDepositProcessorL1.l2TargetDispenser();
+ customExpect(l2TargetDispenser, globalsInstance["arbitrumTargetDispenserL2Address"], log + ", function: l2TargetDispenser()");
+}
+
+// Check checkEthereumDepositProcessor: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkEthereumDepositProcessor(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const ethereumDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + ethereumDepositProcessorL1.address;
+ // Check OLAS token
+ const olas = await ethereumDepositProcessorL1.olas();
+ customExpect(olas, globalsInstance["olasAddress"], log + ", function: olas()");
+
+ // Check dispenser
+ const dispenser = await ethereumDepositProcessorL1.dispenser();
+ customExpect(dispenser, globalsInstance["dispenserAddress"], log + ", function: dispenser()");
+
+ // Check L1 staking factory
+ const stakingFactory = await ethereumDepositProcessorL1.stakingFactory();
+ customExpect(stakingFactory, globalsInstance["serviceStakingFactoryAddress"], log + ", function: stakingFactory()");
+
+ // Check L1 timelock
+ const timelock = await ethereumDepositProcessorL1.timelock();
+ customExpect(timelock, globalsInstance["timelockAddress"], log + ", function: timelock()");
+}
+
+// Check GnosisDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkGnosisDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const gnosisDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + gnosisDepositProcessorL1.address;
+ await checkDepositProcessorL1(gnosisDepositProcessorL1, globalsInstance, log);
+
+ // Check L1 token relayer
+ const l1TokenRelayer = await gnosisDepositProcessorL1.l1TokenRelayer();
+ customExpect(l1TokenRelayer, globalsInstance["gnosisOmniBridgeAddress"], log + ", function: l1TokenRelayer()");
+
+ // Check L1 message relayer
+ const l1MessageRelayer = await gnosisDepositProcessorL1.l1MessageRelayer();
+ customExpect(l1MessageRelayer, globalsInstance["gnosisAMBForeignAddress"], log + ", function: l1MessageRelayer()");
+
+ // Check L2 target chain Id
+ const l2TargetChainId = await gnosisDepositProcessorL1.l2TargetChainId();
+ customExpect(l2TargetChainId.toString(), globalsInstance["gnosisL2TargetChainId"], log + ", function: l2TargetChainId()");
+
+ // Check L2 target dispenser
+ const l2TargetDispenser = await gnosisDepositProcessorL1.l2TargetDispenser();
+ customExpect(l2TargetDispenser, globalsInstance["gnosisTargetDispenserL2Address"], log + ", function: l2TargetDispenser()");
+}
+
+// Check OptimismDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkOptimismDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const optimismDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName, 1);
+
+ log += ", address: " + optimismDepositProcessorL1.address;
+ await checkDepositProcessorL1(optimismDepositProcessorL1, globalsInstance, log);
+
+ // Check L1 token relayer
+ const l1TokenRelayer = await optimismDepositProcessorL1.l1TokenRelayer();
+ customExpect(l1TokenRelayer, globalsInstance["optimisticL1StandardBridgeProxyAddress"], log + ", function: l1TokenRelayer()");
+
+ // Check L1 message relayer
+ const l1MessageRelayer = await optimismDepositProcessorL1.l1MessageRelayer();
+ customExpect(l1MessageRelayer, globalsInstance["optimisticL1CrossDomainMessengerProxyAddress"], log + ", function: l1MessageRelayer()");
+
+ // Check L2 target chain Id
+ const l2TargetChainId = await optimismDepositProcessorL1.l2TargetChainId();
+ customExpect(l2TargetChainId.toString(), globalsInstance["optimisticL2TargetChainId"], log + ", function: l2TargetChainId()");
+
+ // Check L2 OLAS address
+ const olasL2 = await optimismDepositProcessorL1.olasL2();
+ customExpect(olasL2, globalsInstance["optimisticOLASAddress"], log + ", function: olasL2()");
+
+ // Check L2 target dispenser
+ const l2TargetDispenser = await optimismDepositProcessorL1.l2TargetDispenser();
+ customExpect(l2TargetDispenser, globalsInstance["optimismTargetDispenserL2Address"], log + ", function: l2TargetDispenser()");
+}
+
+// Check BaseDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkBaseDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const baseDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + baseDepositProcessorL1.address;
+ await checkDepositProcessorL1(baseDepositProcessorL1, globalsInstance, log);
+
+ // Check L1 token relayer
+ const l1TokenRelayer = await baseDepositProcessorL1.l1TokenRelayer();
+ customExpect(l1TokenRelayer, globalsInstance["baseL1StandardBridgeProxyAddress"], log + ", function: l1TokenRelayer()");
+
+ // Check L1 message relayer
+ const l1MessageRelayer = await baseDepositProcessorL1.l1MessageRelayer();
+ customExpect(l1MessageRelayer, globalsInstance["baseL1CrossDomainMessengerProxyAddress"], log + ", function: l1MessageRelayer()");
+
+ // Check L2 target chain Id
+ const l2TargetChainId = await baseDepositProcessorL1.l2TargetChainId();
+ customExpect(l2TargetChainId.toString(), globalsInstance["baseL2TargetChainId"], log + ", function: l2TargetChainId()");
+
+ // Check L2 OLAS address
+ const olasL2 = await baseDepositProcessorL1.olasL2();
+ customExpect(olasL2, globalsInstance["baseOLASAddress"], log + ", function: olasL2()");
+
+ // Check L2 target dispenser
+ const l2TargetDispenser = await baseDepositProcessorL1.l2TargetDispenser();
+ customExpect(l2TargetDispenser, globalsInstance["baseTargetDispenserL2Address"], log + ", function: l2TargetDispenser()");
+}
+
+// Check PolygonDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkPolygonDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const polygonDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + polygonDepositProcessorL1.address;
+ await checkDepositProcessorL1(polygonDepositProcessorL1, globalsInstance, log);
+
+ // Check L1 token relayer
+ const l1TokenRelayer = await polygonDepositProcessorL1.l1TokenRelayer();
+ customExpect(l1TokenRelayer, globalsInstance["polygonRootChainManagerProxyAddress"], log + ", function: l1TokenRelayer()");
+
+ // Check L1 message relayer
+ const l1MessageRelayer = await polygonDepositProcessorL1.l1MessageRelayer();
+ customExpect(l1MessageRelayer, globalsInstance["polygonFXRootAddress"], log + ", function: l1MessageRelayer()");
+
+ // Check L2 target chain Id
+ const l2TargetChainId = await polygonDepositProcessorL1.l2TargetChainId();
+ customExpect(l2TargetChainId.toString(), globalsInstance["polygonL2TargetChainId"], log + ", function: l2TargetChainId()");
+
+ // Check L1 checkpoint manager
+ const checkpointManager = await polygonDepositProcessorL1.checkpointManager();
+ customExpect(checkpointManager, globalsInstance["polygonCheckpointManagerAddress"], log + ", function: checkpointManager()");
+
+ // Check L1 predicate
+ const predicate = await polygonDepositProcessorL1.predicate();
+ customExpect(predicate, globalsInstance["polygonERC20PredicateAddress"], log + ", function: predicate()");
+
+ // Check L2 target dispenser
+ const l2TargetDispenser = await polygonDepositProcessorL1.l2TargetDispenser();
+ customExpect(l2TargetDispenser, globalsInstance["polygonTargetDispenserL2Address"], log + ", function: l2TargetDispenser()");
+}
+
+// Check CeloDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkCeloDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const celoDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + celoDepositProcessorL1.address;
+ await checkDepositProcessorL1(celoDepositProcessorL1, globalsInstance, log);
+
+ // Check L1 token relayer
+ const l1TokenRelayer = await celoDepositProcessorL1.l1TokenRelayer();
+ customExpect(l1TokenRelayer, globalsInstance["wormholeL1TokenRelayerAddress"], log + ", function: l1TokenRelayer()");
+
+ // Check L1 message relayer
+ const l1MessageRelayer = await celoDepositProcessorL1.l1MessageRelayer();
+ customExpect(l1MessageRelayer, globalsInstance["wormholeL1MessageRelayerAddress"], log + ", function: l1MessageRelayer()");
+
+ // Check L2 target chain Id
+ const l2TargetChainId = await celoDepositProcessorL1.l2TargetChainId();
+ customExpect(l2TargetChainId.toString(), globalsInstance["celoL2TargetChainId"], log + ", function: l2TargetChainId()");
+
+ // Check L1 wormhole core
+ const wormhole = await celoDepositProcessorL1.wormhole();
+ customExpect(wormhole, globalsInstance["wormholeL1CoreAddress"], log + ", function: wormhole()");
+
+ // Check L2 wormhole chain Id format
+ const wormholeTargetChainId = await celoDepositProcessorL1.wormholeTargetChainId();
+ customExpect(wormholeTargetChainId.toString(), globalsInstance["celoWormholeL2TargetChainId"], log + ", function: wormholeTargetChainId()");
+
+ // Check L2 target dispenser
+ const l2TargetDispenser = await celoDepositProcessorL1.l2TargetDispenser();
+ customExpect(l2TargetDispenser, globalsInstance["celoTargetDispenserL2Address"], log + ", function: l2TargetDispenser()");
+}
+
+// Check TargetDispenserL2: contract, globalsInstance
+async function checkTargetDispenserL2(targetDispenserL2, globalsInstance, log) {
+ log += ", address: " + targetDispenserL2.address;
+ // Check contract owner
+ const owner = await targetDispenserL2.owner();
+ customExpect(owner, globalsInstance["bridgeMediatorAddress"], log + ", function: owner()");
+
+ // Check L2 OLAS token
+ const olas = await targetDispenserL2.olas();
+ customExpect(olas, globalsInstance["olasAddress"], log + ", function: olas()");
+
+ // Check L2 staking factory
+ const stakingFactory = await targetDispenserL2.stakingFactory();
+ customExpect(stakingFactory, globalsInstance["serviceStakingFactoryAddress"], log + ", function: stakingFactory()");
+
+ // Check L1 source chain Id
+ const l1SourceChainId = await targetDispenserL2.l1SourceChainId();
+ customExpect(l1SourceChainId.toString(), globalsInstance["l1ChainId"], log + ", function: l1SourceChainId()");
+}
+
+// Check PolygonTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkPolygonTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const polygonTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + polygonTargetDispenserL2.address;
+ await checkTargetDispenserL2(polygonTargetDispenserL2, globalsInstance, log);
+
+ // Check L2 message relayer
+ const l2MessageRelayer = await polygonTargetDispenserL2.l2MessageRelayer();
+ customExpect(l2MessageRelayer, globalsInstance["polygonFXChildAddress"], log + ", function: l2MessageRelayer()");
+
+ // Check L1 deposit processor
+ const l1DepositProcessor = await polygonTargetDispenserL2.l1DepositProcessor();
+ customExpect(l1DepositProcessor, globalsInstance["polygonDepositProcessorL1Address"], log + ", function: l1DepositProcessor()");
+}
+
+// Check GnosisTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkGnosisTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const gnosisTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + gnosisTargetDispenserL2.address;
+ await checkTargetDispenserL2(gnosisTargetDispenserL2, globalsInstance, log);
+
+ // Check L2 message relayer
+ const l2MessageRelayer = await gnosisTargetDispenserL2.l2MessageRelayer();
+ customExpect(l2MessageRelayer, globalsInstance["gnosisAMBHomeAddress"], log + ", function: l2MessageRelayer()");
+
+ // Check L1 deposit processor
+ const l1DepositProcessor = await gnosisTargetDispenserL2.l1DepositProcessor();
+ customExpect(l1DepositProcessor, globalsInstance["gnosisDepositProcessorL1Address"], log + ", function: l1DepositProcessor()");
+}
+
+// Check ArbitrumTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkArbitrumTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const arbitrumTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + arbitrumTargetDispenserL2.address;
+ await checkTargetDispenserL2(arbitrumTargetDispenserL2, globalsInstance, log);
+
+ // Check L2 message relayer
+ const l2MessageRelayer = await arbitrumTargetDispenserL2.l2MessageRelayer();
+ customExpect(l2MessageRelayer, globalsInstance["arbitrumArbSysAddress"], log + ", function: l2MessageRelayer()");
+
+ // Check L1 deposit processor
+ const l1DepositProcessor = await arbitrumTargetDispenserL2.l1DepositProcessor();
+ customExpect(l1DepositProcessor, globalsInstance["arbitrumDepositProcessorL1Address"], log + ", function: l1DepositProcessor()");
+}
+
+// Check OptimismTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkOptimismTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const optimismTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + optimismTargetDispenserL2.address;
+ await checkTargetDispenserL2(optimismTargetDispenserL2, globalsInstance, log);
+
+ // Check L2 message relayer
+ const l2MessageRelayer = await optimismTargetDispenserL2.l2MessageRelayer();
+ customExpect(l2MessageRelayer, globalsInstance["optimisticL2CrossDomainMessengerAddress"], log + ", function: l2MessageRelayer()");
+
+ // Check L1 deposit processor
+ const l1DepositProcessor = await optimismTargetDispenserL2.l1DepositProcessor();
+ customExpect(l1DepositProcessor, globalsInstance["optimismDepositProcessorL1Address"], log + ", function: l1DepositProcessor()");
+}
+
+// Check BaseTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkBaseTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const baseTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + baseTargetDispenserL2.address;
+ await checkTargetDispenserL2(baseTargetDispenserL2, globalsInstance, log);
+
+ // Check L2 message relayer
+ const l2MessageRelayer = await baseTargetDispenserL2.l2MessageRelayer();
+ customExpect(l2MessageRelayer, globalsInstance["baseL2CrossDomainMessengerAddress"], log + ", function: l2MessageRelayer()");
+
+ // Check L1 deposit processor
+ const l1DepositProcessor = await baseTargetDispenserL2.l1DepositProcessor();
+ customExpect(l1DepositProcessor, globalsInstance["baseDepositProcessorL1Address"], log + ", function: l1DepositProcessor()");
+}
+
+// Check CeloTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name
+async function checkCeloTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) {
+ // Check the bytecode
+ await checkBytecode(provider, configContracts, contractName, log);
+
+ // Get the contract instance
+ const celoTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName);
+
+ log += ", address: " + celoTargetDispenserL2.address;
+ await checkTargetDispenserL2(celoTargetDispenserL2, globalsInstance, log);
+
+ // Check L2 message relayer
+ const l2MessageRelayer = await celoTargetDispenserL2.l2MessageRelayer();
+ customExpect(l2MessageRelayer, globalsInstance["wormholeL2MessageRelayer"], log + ", function: l2MessageRelayer()");
+
+ // Check L1 deposit processor
+ const l1DepositProcessor = await celoTargetDispenserL2.l1DepositProcessor();
+ customExpect(l1DepositProcessor, globalsInstance["celoDepositProcessorL1Address"], log + ", function: l1DepositProcessor()");
+
+ // Check L2 wormhole core
+ const wormhole = await celoTargetDispenserL2.wormhole();
+ customExpect(wormhole, globalsInstance["wormholeL2CoreAddress"], log + ", function: wormhole()");
+}
+
async function main() {
// Check for the API keys
- if (!process.env.ALCHEMY_API_KEY_MAINNET || !process.env.ALCHEMY_API_KEY_GOERLI ||
- !process.env.ALCHEMY_API_KEY_MATIC || !process.env.ALCHEMY_API_KEY_MUMBAI) {
+ if (!process.env.ALCHEMY_API_KEY_MAINNET || !process.env.ALCHEMY_API_KEY_SEPOLIA ||
+ !process.env.ALCHEMY_API_KEY_MATIC || !process.env.ALCHEMY_API_KEY_AMOY) {
console.log("Check API keys!");
return;
}
@@ -260,87 +659,144 @@ async function main() {
const dataFromJSON = fs.readFileSync(configFile, "utf8");
const configs = JSON.parse(dataFromJSON);
- const numChains = configs.length;
// ################################# VERIFY CONTRACTS WITH REPO #################################
- // For now gnosis chains are not supported
- const networks = {
- "mainnet": "etherscan",
- "goerli": "goerli.etherscan",
- };
-
console.log("\nVerifying deployed contracts vs the repo... If no error is output, then the contracts are correct.");
- // Traverse all chains
- for (let i = 0; i < numChains; i++) {
- // Skip gnosis chains
- if (!networks[configs[i]["name"]]) {
+ // Currently the verification is fo mainnet only
+ const network = "etherscan";
+ const contracts = configs[0]["contracts"];
+
+ // Verify contracts
+ for (let i = 0; i < contracts.length; i++) {
+ console.log("Checking " + contracts[i]["name"]);
+ const execSync = require("child_process").execSync;
+ try {
+ execSync("scripts/audit_chains/audit_repo_contract.sh " + network + " " + contracts[i]["name"] + " " + contracts[i]["address"]);
+ } catch (error) {
continue;
}
-
- console.log("\n\nNetwork:", configs[i]["name"]);
- const network = networks[configs[i]["name"]];
- const contracts = configs[i]["contracts"];
-
- // Verify contracts
- for (let j = 0; j < contracts.length; j++) {
- console.log("Checking " + contracts[j]["name"]);
- const execSync = require("child_process").execSync;
- try {
- execSync("scripts/audit_chains/audit_repo_contract.sh " + network + " " + contracts[j]["name"] + " " + contracts[j]["address"]);
- } catch (error) {
- continue;
- }
- }
}
// ################################# /VERIFY CONTRACTS WITH REPO #################################
// ################################# VERIFY CONTRACTS SETUP #################################
const globalNames = {
"mainnet": "scripts/deployment/globals_mainnet.json",
- "goerli": "scripts/deployment/globals_goerli.json",
+ "polygon": "scripts/deployment/staking/polygon/globals_polygon_mainnet.json",
+ "gnosis": "scripts/deployment/staking/gnosis/globals_gnosis_mainnet.json",
+ "arbitrumOne": "scripts/deployment/staking/arbitrum/globals_arbitrum_one.json",
+ "optimistic": "scripts/deployment/staking/optimistic/globals_optimistic_mainnet.json",
+ "base": "scripts/deployment/staking/base/globals_base_mainnet.json",
+ "celo": "scripts/deployment/staking/celo/globals_celo_mainnet.json"
};
+ const globals = new Array();
+ for (let k in globalNames) {
+ const dataJSON = fs.readFileSync(globalNames[k], "utf8");
+ globals.push(JSON.parse(dataJSON));
+ }
+ // Special case for staking (also on L1)
+ const dataJSON = fs.readFileSync("scripts/deployment/staking/globals_mainnet.json", "utf8");
+ const globalsStaking = JSON.parse(dataJSON);
+
+
const providerLinks = {
"mainnet": "https://eth-mainnet.g.alchemy.com/v2/" + process.env.ALCHEMY_API_KEY_MAINNET,
- "goerli": "https://eth-goerli.g.alchemy.com/v2/" + process.env.ALCHEMY_API_KEY_GOERLI,
+ "polygon": "https://polygon-mainnet.g.alchemy.com/v2/" + process.env.ALCHEMY_API_KEY_MATIC,
+ "gnosis": "https://rpc.gnosischain.com",
+ "arbitrumOne": "https://arb1.arbitrum.io/rpc",
+ "optimistic": "https://optimism.drpc.org",
+ "base": "https://mainnet.base.org",
+ "celo": "https://forno.celo.org"
};
- // Get all the globals processed
- const globals = new Array();
const providers = new Array();
- for (let i = 0; i < numChains; i++) {
- const dataJSON = fs.readFileSync(globalNames[configs[i]["name"]], "utf8");
- globals.push(JSON.parse(dataJSON));
- const provider = new ethers.providers.JsonRpcProvider(providerLinks[configs[i]["name"]]);
+ for (let k in providerLinks) {
+ const provider = new ethers.providers.JsonRpcProvider(providerLinks[k]);
providers.push(provider);
}
console.log("\nVerifying deployed contracts setup... If no error is output, then the contracts are correct.");
// L1 contracts
- for (let i = 0; i < 2; i++) {
- console.log("\n######## Verifying setup on CHAIN ID", configs[i]["chainId"]);
+ console.log("\n######## Verifying setup on CHAIN ID", configs[0]["chainId"]);
- const initLog = "ChainId: " + configs[i]["chainId"] + ", network: " + configs[i]["name"];
+ let initLog = "ChainId: " + configs[0]["chainId"] + ", network: " + configs[0]["name"];
- let log = initLog + ", contract: " + "DonatorBlacklist";
- await checkDonatorBlacklist(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "DonatorBlacklist", log);
+ let log = initLog + ", contract: " + "DonatorBlacklist";
+ await checkDonatorBlacklist(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "DonatorBlacklist", log);
- log = initLog + ", contract: " + "TokenomicsProxy";
- await checkTokenomicsProxy(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "TokenomicsProxy", log);
+ log = initLog + ", contract: " + "TokenomicsProxy";
+ await checkTokenomicsProxy(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "TokenomicsProxy", log);
- log = initLog + ", contract: " + "Treasury";
- await checkTreasury(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "Treasury", log);
+ log = initLog + ", contract: " + "Treasury";
+ await checkTreasury(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "Treasury", log);
- log = initLog + ", contract: " + "GenericBondCalculator";
- await checkGenericBondCalculator(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "GenericBondCalculator", log);
+ log = initLog + ", contract: " + "GenericBondCalculator";
+ await checkGenericBondCalculator(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "GenericBondCalculator", log);
- log = initLog + ", contract: " + "Dispenser";
- await checkDispenser(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "Dispenser", log);
+ log = initLog + ", contract: " + "Dispenser";
+ await checkDispenser(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "Dispenser", log);
- log = initLog + ", contract: " + "Depository";
- await checkDepository(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "Depository", log);
- }
+ log = initLog + ", contract: " + "Depository";
+ await checkDepository(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "Depository", log);
+
+ log = initLog + ", contract: " + "ArbitrumDepositProcessorL1";
+ await checkArbitrumDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "ArbitrumDepositProcessorL1", log);
+
+ log = initLog + ", contract: " + "EthereumDepositProcessor";
+ await checkEthereumDepositProcessor(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "EthereumDepositProcessor", log);
+
+ log = initLog + ", contract: " + "GnosisDepositProcessorL1";
+ await checkGnosisDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "GnosisDepositProcessorL1", log);
+
+ log = initLog + ", contract: " + "OptimismDepositProcessorL1";
+ await checkOptimismDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "OptimismDepositProcessorL1", log);
+
+ log = initLog + ", contract: " + "BaseDepositProcessorL1";
+ await checkBaseDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "OptimismDepositProcessorL1", log);
+
+ log = initLog + ", contract: " + "PolygonDepositProcessorL1";
+ await checkPolygonDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "PolygonDepositProcessorL1", log);
+
+ log = initLog + ", contract: " + "CeloDepositProcessorL1";
+ await checkCeloDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "WormholeDepositProcessorL1", log);
+
+ // L2 contracts
+ // Polygon
+ console.log("\n######## Verifying setup on CHAIN ID", configs[11]["chainId"]);
+ initLog = "ChainId: " + configs[11]["chainId"] + ", network: " + configs[11]["name"];
+ log = initLog + ", contract: " + "PolygonTargetDispenserL2";
+ await checkPolygonTargetDispenserL2(configs[11]["chainId"], providers[1], globals[1], configs[11]["contracts"], "PolygonTargetDispenserL2", log);
+
+ // Gnosis
+ console.log("\n######## Verifying setup on CHAIN ID", configs[7]["chainId"]);
+ initLog = "ChainId: " + configs[7]["chainId"] + ", network: " + configs[7]["name"];
+ log = initLog + ", contract: " + "GnosisTargetDispenserL2";
+ await checkGnosisTargetDispenserL2(configs[7]["chainId"], providers[2], globals[2], configs[7]["contracts"], "GnosisTargetDispenserL2", log);
+
+ // Arbitrum
+ console.log("\n######## Verifying setup on CHAIN ID", configs[1]["chainId"]);
+ initLog = "ChainId: " + configs[1]["chainId"] + ", network: " + configs[1]["name"];
+ log = initLog + ", contract: " + "ArbitrumTargetDispenserL2";
+ await checkArbitrumTargetDispenserL2(configs[1]["chainId"], providers[3], globals[3], configs[1]["contracts"], "ArbitrumTargetDispenserL2", log);
+
+ // Base
+ console.log("\n######## Verifying setup on CHAIN ID", configs[3]["chainId"]);
+ initLog = "ChainId: " + configs[3]["chainId"] + ", network: " + configs[3]["name"];
+ log = initLog + ", contract: " + "BaseTargetDispenserL2";
+ await checkBaseTargetDispenserL2(configs[3]["chainId"], providers[5], globals[5], configs[3]["contracts"], "OptimismTargetDispenserL2", log);
+
+ // Celo
+ console.log("\n######## Verifying setup on CHAIN ID", configs[5]["chainId"]);
+ initLog = "ChainId: " + configs[5]["chainId"] + ", network: " + configs[5]["name"];
+ log = initLog + ", contract: " + "CeloTargetDispenserL2";
+ await checkCeloTargetDispenserL2(configs[5]["chainId"], providers[6], globals[6], configs[5]["contracts"], "WormholeTargetDispenserL2", log);
+
+ // Optimism
+ console.log("\n######## Verifying setup on CHAIN ID", configs[9]["chainId"]);
+ initLog = "ChainId: " + configs[9]["chainId"] + ", network: " + configs[9]["name"];
+ log = initLog + ", contract: " + "OptimismTargetDispenserL2";
+ await checkOptimismTargetDispenserL2(configs[9]["chainId"], providers[4], globals[4], configs[9]["contracts"], "OptimismTargetDispenserL2", log);
// ################################# /VERIFY CONTRACTS SETUP #################################
}
diff --git a/scripts/deployment/README.md b/scripts/deployment/README.md
index 1376022f..66b9e2e0 100644
--- a/scripts/deployment/README.md
+++ b/scripts/deployment/README.md
@@ -1,5 +1,8 @@
# Deployment scripts
-This folder contains the scripts to deploy Autonolas tokenomics. These scripts correspond to the steps in the full deployment procedure (as described in [deployment.md](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/docs/deployment.md)).
+This folder contains the scripts to deploy Autonolas tokenomics.
+These scripts correspond to the steps in the full deployment procedure (as described in [deployment.md](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/docs/deployment.md)).
+
+For the Tokenomics 1.2, refer to the following deployment procedure: [deployment_v1.2.md](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/docs/deployment_v1.2.md).
## Observations
- There are several files with global parameters based on the corresponding network. In order to work with the configuration, please copy `gobals_network.json` file to file the `gobals.json` one, where `network` is the corresponding network. For example: `cp gobals_goerli.json gobals.json`.
diff --git a/scripts/deployment/deploy_07_dispenser.js b/scripts/deployment/deploy_07_dispenser.js
index f62d53f7..9fb45ef4 100644
--- a/scripts/deployment/deploy_07_dispenser.js
+++ b/scripts/deployment/deploy_07_dispenser.js
@@ -26,25 +26,35 @@ async function main() {
console.log("EOA is:", deployer);
// Get all the necessary contract addresses
+ const olasAddress = parsedData.olasAddress;
const tokenomicsProxyAddress = parsedData.tokenomicsProxyAddress;
const treasuryAddress = parsedData.treasuryAddress;
+ const voteWeightingAddress = parsedData.voteWeightingAddress;
+ const retainerAddress = parsedData.retainerAddress;
+ const maxNumClaimingEpochs = parsedData.maxNumClaimingEpochs;
+ const maxNumStakingTargets = parsedData.maxNumStakingTargets;
+ const minStakingWeight = parsedData.minStakingWeight;
+ const maxStakingIncentive = parsedData.maxStakingIncentive;
// Transaction signing and execution
console.log("7. EOA to deploy Dispenser");
const Dispenser = await ethers.getContractFactory("Dispenser");
console.log("You are signing the following transaction: Dispenser.connect(EOA).deploy()");
- const dispenser = await Dispenser.connect(EOA).deploy(tokenomicsProxyAddress, treasuryAddress);
+ const dispenser = await Dispenser.connect(EOA).deploy(olasAddress, tokenomicsProxyAddress, treasuryAddress,
+ voteWeightingAddress, retainerAddress, maxNumClaimingEpochs, maxNumStakingTargets, minStakingWeight,
+ maxStakingIncentive);
const result = await dispenser.deployed();
- // If on goerli, wait a minute for the transaction completion
- if (providerName === "goerli") {
- await new Promise(r => setTimeout(r, 60000));
- }
// Transaction details
console.log("Contract deployment: Dispenser");
console.log("Contract address:", dispenser.address);
console.log("Transaction:", result.deployTransaction.hash);
+ // If on sepolia, wait half a minute for the transaction completion
+ if (providerName === "sepolia") {
+ await new Promise(r => setTimeout(r, 30000));
+ }
+
// Contract verification
if (parsedData.contractVerification) {
const execSync = require("child_process").execSync;
diff --git a/scripts/deployment/globals_mainnet.json b/scripts/deployment/globals_mainnet.json
index 3f165c8f..9344fce1 100644
--- a/scripts/deployment/globals_mainnet.json
+++ b/scripts/deployment/globals_mainnet.json
@@ -1 +1 @@
-{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"mainnet","olasAddress":"0x0001A500A6B18995B03f44bb040A5fFc28E45CB0","timelockAddress":"0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE","veOLASAddress":"0x7e01A500805f8A52Fad229b3015AD130A332B7b3","governorAddress":"0x34C895f302D0b5cf52ec0Edd3945321EB0f83dd5","governorTwoAddress":"0x4E3e48bA826b15214FDe72a50BFd17aB286B584E","componentRegistryAddress":"0x15bd56669F57192a97dF41A2aa8f4403e9491776","agentRegistryAddress":"0x2F1f7D38e4772884b88f3eCd8B6b9faCdC319112","serviceRegistryAddress":"0x48b6af7B12C71f09e2fC8aF4855De4Ff54e775cA","epochLen":"2592000","donatorBlacklistAddress":"0xE85791B18F5df42163092Acc5C9da1c479AFEa9d","tokenomicsAddress":"0x87f89F94033305791B6269AE2F9cF4e09983E56e","tokenomicsProxyAddress":"0xc096362fa6f4A4B1a9ea68b1043416f3381ce300","treasuryAddress":"0xa0DA53447C0f6C4987964d8463da7e6628B30f82","genericBondCalculatorAddress":"0x1521918961bDBC9Ed4C67a7103D5999e4130E6CB","depositoryAddress":"0x52A043bcebdB2f939BaEF2E8b6F01652290eAB3f","dispenserAddress":"0xeED0000fE94d7cfeF4Dc0CA86a223f0F603A61B8","tokenomicsTwoAddress":"0xD599ED4a5c45Fa66AA3C474b00701Fd452a2C30e","OLAS_ETH_PairAddress":"0x09D1d767eDF8Fa23A64C51fa559E0688E526812F","depositoryTwoAddress":"0xfF8697d8d2998d6AA2e09B405795C6F4BEeB0C81","XOLAS_WXDAI_PairAddress":"0x27df632fd0dcf191C418c803801D521cd579F18e","tokenomicsThreeAddress":"0x2C1633765c66a7CF0EC801a1046347bBee7344C9"}
\ No newline at end of file
+{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"mainnet","olasAddress":"0x0001A500A6B18995B03f44bb040A5fFc28E45CB0","timelockAddress":"0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE","veOLASAddress":"0x7e01A500805f8A52Fad229b3015AD130A332B7b3","governorAddress":"0x34C895f302D0b5cf52ec0Edd3945321EB0f83dd5","governorTwoAddress":"0x4E3e48bA826b15214FDe72a50BFd17aB286B584E","componentRegistryAddress":"0x15bd56669F57192a97dF41A2aa8f4403e9491776","agentRegistryAddress":"0x2F1f7D38e4772884b88f3eCd8B6b9faCdC319112","serviceRegistryAddress":"0x48b6af7B12C71f09e2fC8aF4855De4Ff54e775cA","epochLen":"2592000","donatorBlacklistAddress":"0xE85791B18F5df42163092Acc5C9da1c479AFEa9d","tokenomicsAddress":"0x87f89F94033305791B6269AE2F9cF4e09983E56e","tokenomicsProxyAddress":"0xc096362fa6f4A4B1a9ea68b1043416f3381ce300","treasuryAddress":"0xa0DA53447C0f6C4987964d8463da7e6628B30f82","genericBondCalculatorAddress":"0x1521918961bDBC9Ed4C67a7103D5999e4130E6CB","depositoryAddress":"0x52A043bcebdB2f939BaEF2E8b6F01652290eAB3f","dispenserAddress":"0x5650300fCBab43A0D7D02F8Cb5d0f039402593f0","tokenomicsTwoAddress":"0xD599ED4a5c45Fa66AA3C474b00701Fd452a2C30e","OLAS_ETH_PairAddress":"0x09D1d767eDF8Fa23A64C51fa559E0688E526812F","depositoryTwoAddress":"0xfF8697d8d2998d6AA2e09B405795C6F4BEeB0C81","XOLAS_WXDAI_PairAddress":"0x27df632fd0dcf191C418c803801D521cd579F18e","tokenomicsThreeAddress":"0x2C1633765c66a7CF0EC801a1046347bBee7344C9","voteWeightingAddress":"0x95418b46d5566d3d1ea62c12aea91227e566c5c1","retainerAddress":"0x000000000000000000000000000000000000000000000000000000000000dEaD","maxNumClaimingEpochs":"1","maxNumStakingTargets":"10","minStakingWeight":"100","maxStakingIncentive":"30000000000000000000000"}
\ No newline at end of file
diff --git a/scripts/deployment/staking/arbitrum/deploy_21_change_owner.js b/scripts/deployment/staking/arbitrum/deploy_21_change_owner.js
new file mode 100644
index 00000000..f05cdf37
--- /dev/null
+++ b/scripts/deployment/staking/arbitrum/deploy_21_change_owner.js
@@ -0,0 +1,48 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+ const arbitrumTargetDispenserL2Address = parsedData.arbitrumTargetDispenserL2Address;
+ const bridgeMediatorAddress = parsedData.bridgeMediatorAddress;
+
+ let networkURL = parsedData.networkURL;
+ const provider = new ethers.providers.JsonRpcProvider(networkURL);
+ const signers = await ethers.getSigners();
+
+ let EOA;
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Transaction signing and execution
+ console.log("21. EOA to change owner in ArbitrumTargetDispenserL2");
+ const arbitrumTargetDispenserL2 = await ethers.getContractAt("ArbitrumTargetDispenserL2", arbitrumTargetDispenserL2Address);
+ console.log("You are signing the following transaction: ArbitrumTargetDispenserL2.connect(EOA).changeOwner()");
+ const result = await arbitrumTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress);
+
+ // Transaction details
+ console.log("Contract deployment: ArbitrumTargetDispenserL2");
+ console.log("Contract address:", arbitrumTargetDispenserL2.address);
+ console.log("Transaction:", result.hash);
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/arbitrum/globals_arbitrum_one.json b/scripts/deployment/staking/arbitrum/globals_arbitrum_one.json
new file mode 100644
index 00000000..cc50b481
--- /dev/null
+++ b/scripts/deployment/staking/arbitrum/globals_arbitrum_one.json
@@ -0,0 +1 @@
+{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"arbitrumOne","networkURL":"https://arb1.arbitrum.io/rpc","gasPriceInGwei":"5","olasAddress":"0x064F8B858C2A603e1b106a2039f5446D32dc81c1","serviceStakingFactoryAddress":"0xEB5638eefE289691EcE01943f768EDBF96258a80","bridgeMediatorAddress":"0x4d30F68F5AA342d296d4deE4bB1Cacca912dA70F","arbitrumArbSysAddress":"0x0000000000000000000000000000000000000064","l1ChainId":"1","arbitrumDepositProcessorL1Address":"0x5e13E07006D68B097DCb5979ef5545C4f9156162","arbitrumTargetDispenserL2Address":"0x10c5525F77F13b28f42c5626240c001c2D57CAd4"}
\ No newline at end of file
diff --git a/scripts/deployment/staking/arbitrum/send_tokens_and_message.js b/scripts/deployment/staking/arbitrum/send_tokens_and_message.js
index a691b901..482790f2 100644
--- a/scripts/deployment/staking/arbitrum/send_tokens_and_message.js
+++ b/scripts/deployment/staking/arbitrum/send_tokens_and_message.js
@@ -163,7 +163,7 @@ const main = async () => {
await tx.wait();
// tx back to L1: https://sepolia.arbiscan.io/tx/0xea8119b1030bb223a896680d9c4ea03877beee08927ef1b8a9532ce48db68c55
- // Finalized tx on L1:
+ // Finalized tx on L1: https://sepolia.etherscan.io/tx/0x5f61dd72b5feb31af563f7af76402e523e1e871bdac7f1a82bb0ffefcd333ebb
// Use the following script to finalize L2-L1 transaction:
// https://github.com/OffchainLabs/arbitrum-tutorials/blob/master/packages/outbox-execute/scripts/exec.js
diff --git a/scripts/deployment/staking/base/deploy_07_base_targer_dispenser.js b/scripts/deployment/staking/base/deploy_07_base_targer_dispenser.js
new file mode 100644
index 00000000..13bd32fc
--- /dev/null
+++ b/scripts/deployment/staking/base/deploy_07_base_targer_dispenser.js
@@ -0,0 +1,75 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+
+ let networkURL = parsedData.networkURL;
+ if (providerName === "polygon") {
+ if (!process.env.ALCHEMY_API_KEY_MATIC) {
+ console.log("set ALCHEMY_API_KEY_MATIC env variable");
+ }
+ networkURL += process.env.ALCHEMY_API_KEY_MATIC;
+ } else if (providerName === "polygonAmoy") {
+ if (!process.env.ALCHEMY_API_KEY_AMOY) {
+ console.log("set ALCHEMY_API_KEY_AMOY env variable");
+ return;
+ }
+ networkURL += process.env.ALCHEMY_API_KEY_AMOY;
+ }
+
+ const provider = new ethers.providers.JsonRpcProvider(networkURL);
+ const signers = await ethers.getSigners();
+
+ let EOA;
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Transaction signing and execution
+ console.log("7. EOA to deploy OptimismTargetDispenserL2 for Base");
+ const OptimismTargetDispenserL2 = await ethers.getContractFactory("OptimismTargetDispenserL2");
+ console.log("You are signing the following transaction: OptimismTargetDispenserL2.connect(EOA).deploy()");
+ const baseTargetDispenserL2 = await OptimismTargetDispenserL2.connect(EOA).deploy(parsedData.olasAddress,
+ parsedData.serviceStakingFactoryAddress, parsedData.baseL2CrossDomainMessengerAddress,
+ parsedData.baseDepositProcessorL1Address, parsedData.l1ChainId);
+ const result = await baseTargetDispenserL2.deployed();
+
+ // Transaction details
+ console.log("Contract deployment: OptimismTargetDispenserL2");
+ console.log("Contract address:", baseTargetDispenserL2.address);
+ console.log("Transaction:", result.deployTransaction.hash);
+
+ // Wait for half a minute for the transaction completion
+ await new Promise(r => setTimeout(r, 30000));
+
+ // Writing updated parameters back to the JSON file
+ parsedData.baseTargetDispenserL2Address = baseTargetDispenserL2.address;
+ fs.writeFileSync(globalsFile, JSON.stringify(parsedData));
+
+ // Contract verification
+ if (parsedData.contractVerification) {
+ const execSync = require("child_process").execSync;
+ execSync("npx hardhat verify --constructor-args scripts/deployment/staking/optimistic/verify_07_base_target_dispenser.js --network " + providerName + " " + baseTargetDispenserL2.address, { encoding: "utf-8" });
+ }
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/base/deploy_71_change_owner.js b/scripts/deployment/staking/base/deploy_71_change_owner.js
new file mode 100644
index 00000000..d959f2e7
--- /dev/null
+++ b/scripts/deployment/staking/base/deploy_71_change_owner.js
@@ -0,0 +1,48 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+ const baseTargetDispenserL2Address = parsedData.baseTargetDispenserL2Address;
+ const bridgeMediatorAddress = parsedData.bridgeMediatorAddress;
+
+ let networkURL = parsedData.networkURL;
+ const provider = new ethers.providers.JsonRpcProvider(networkURL);
+ const signers = await ethers.getSigners();
+
+ let EOA;
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Transaction signing and execution
+ console.log("71. EOA to change owner in OptimismTargetDispenserL2 (Base)");
+ const baseTargetDispenserL2 = await ethers.getContractAt("OptimismTargetDispenserL2", baseTargetDispenserL2Address);
+ console.log("You are signing the following transaction: OptimismTargetDispenserL2.connect(EOA).changeOwner()");
+ const result = await baseTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress);
+
+ // Transaction details
+ console.log("Contract deployment: OptimismTargetDispenserL2");
+ console.log("Contract address:", baseTargetDispenserL2.address);
+ console.log("Transaction:", result.hash);
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/base/globals_base_mainnet.json b/scripts/deployment/staking/base/globals_base_mainnet.json
new file mode 100644
index 00000000..0feae934
--- /dev/null
+++ b/scripts/deployment/staking/base/globals_base_mainnet.json
@@ -0,0 +1 @@
+{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"base","networkURL":"https://mainnet.base.org","gasPriceInGwei":"2","olasAddress":"0x54330d28ca3357F294334BDC454a032e7f353416","serviceStakingFactoryAddress":"0x1cEe30D08943EB58EFF84DD1AB44a6ee6FEff63a","bridgeMediatorAddress":"0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA","baseL2CrossDomainMessengerAddress":"0x4200000000000000000000000000000000000007","l1ChainId":"1","baseDepositProcessorL1Address":"0x42BA1BbD797E4C90F386F03a544F3b62C1f917d0","baseTargetDispenserL2Address":"0xcDdD9D9ABaB36fFa882530D69c73FeE5D4001C2d"}
\ No newline at end of file
diff --git a/scripts/deployment/staking/base/verify_07_base_target_dispenser.js b/scripts/deployment/staking/base/verify_07_base_target_dispenser.js
new file mode 100644
index 00000000..be0fd403
--- /dev/null
+++ b/scripts/deployment/staking/base/verify_07_base_target_dispenser.js
@@ -0,0 +1,12 @@
+const fs = require("fs");
+const globalsFile = "globals.json";
+const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+const parsedData = JSON.parse(dataFromJSON);
+
+module.exports = [
+ parsedData.olasAddress,
+ parsedData.serviceStakingFactoryAddress,
+ parsedData.baseL2CrossDomainMessengerAddress,
+ parsedData.baseDepositProcessorL1Address,
+ parsedData.l1ChainId
+];
\ No newline at end of file
diff --git a/scripts/deployment/staking/celo/deploy_051_change_owner.js b/scripts/deployment/staking/celo/deploy_051_change_owner.js
new file mode 100644
index 00000000..6ca830ec
--- /dev/null
+++ b/scripts/deployment/staking/celo/deploy_051_change_owner.js
@@ -0,0 +1,48 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+ const celoTargetDispenserL2Address = parsedData.celoTargetDispenserL2Address;
+ const bridgeMediatorAddress = parsedData.bridgeMediatorAddress;
+
+ let networkURL = parsedData.networkURL;
+ const provider = new ethers.providers.JsonRpcProvider(networkURL);
+ const signers = await ethers.getSigners();
+
+ let EOA;
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Transaction signing and execution
+ console.log("51. EOA to change owner in WormholeTargetDispenserL2 (Celo)");
+ const celoTargetDispenserL2 = await ethers.getContractAt("WormholeTargetDispenserL2", celoTargetDispenserL2Address);
+ console.log("You are signing the following transaction: WormholeTargetDispenserL2.connect(EOA).changeOwner()");
+ const result = await celoTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress);
+
+ // Transaction details
+ console.log("Contract deployment: WormholeTargetDispenserL2");
+ console.log("Contract address:", celoTargetDispenserL2.address);
+ console.log("Transaction:", result.hash);
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/celo/deploy_05_celo_targer_dispenser.js b/scripts/deployment/staking/celo/deploy_05_celo_targer_dispenser.js
new file mode 100644
index 00000000..cfe1d7b6
--- /dev/null
+++ b/scripts/deployment/staking/celo/deploy_05_celo_targer_dispenser.js
@@ -0,0 +1,76 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+
+ let networkURL = parsedData.networkURL;
+ if (providerName === "polygon") {
+ if (!process.env.ALCHEMY_API_KEY_MATIC) {
+ console.log("set ALCHEMY_API_KEY_MATIC env variable");
+ }
+ networkURL += process.env.ALCHEMY_API_KEY_MATIC;
+ } else if (providerName === "polygonAmoy") {
+ if (!process.env.ALCHEMY_API_KEY_AMOY) {
+ console.log("set ALCHEMY_API_KEY_AMOY env variable");
+ return;
+ }
+ networkURL += process.env.ALCHEMY_API_KEY_AMOY;
+ }
+
+ const provider = new ethers.providers.JsonRpcProvider(networkURL);
+ const signers = await ethers.getSigners();
+
+ let EOA;
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Transaction signing and execution
+ console.log("5. EOA to deploy WormholeTargetDispenserL2");
+ const WormholeTargetDispenserL2 = await ethers.getContractFactory("WormholeTargetDispenserL2");
+ console.log("You are signing the following transaction: WormholeTargetDispenserL2.connect(EOA).deploy()");
+ const celoTargetDispenserL2 = await WormholeTargetDispenserL2.connect(EOA).deploy(parsedData.olasAddress,
+ parsedData.serviceStakingFactoryAddress, parsedData.wormholeL2MessageRelayer,
+ parsedData.celoDepositProcessorL1Address, parsedData.wormholel1ChainId,
+ parsedData.wormholeL2CoreAddress, parsedData.wormholeL2TokenRelayerAddress);
+ const result = await celoTargetDispenserL2.deployed();
+
+ // Transaction details
+ console.log("Contract deployment: WormholeTargetDispenserL2");
+ console.log("Contract address:", celoTargetDispenserL2.address);
+ console.log("Transaction:", result.deployTransaction.hash);
+
+ // Wait for half a minute for the transaction completion
+ await new Promise(r => setTimeout(r, 30000));
+
+ // Writing updated parameters back to the JSON file
+ parsedData.celoTargetDispenserL2Address = celoTargetDispenserL2.address;
+ fs.writeFileSync(globalsFile, JSON.stringify(parsedData));
+
+ // Contract verification
+ if (parsedData.contractVerification) {
+ const execSync = require("child_process").execSync;
+ execSync("npx hardhat verify --constructor-args scripts/deployment/staking/celo/verify_05_celo_target_dispenser.js --network " + providerName + " " + celoTargetDispenserL2.address, { encoding: "utf-8" });
+ }
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/celo/globals_celo_mainnet.json b/scripts/deployment/staking/celo/globals_celo_mainnet.json
new file mode 100644
index 00000000..a6d7d552
--- /dev/null
+++ b/scripts/deployment/staking/celo/globals_celo_mainnet.json
@@ -0,0 +1 @@
+{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"celo","networkURL":"https://forno.celo.org","gasPriceInGwei":"2","olasAddress":"0xaCFfAe8e57Ec6E394Eb1b41939A8CF7892DbDc51","serviceStakingFactoryAddress":"0x1c2cD884127b080F940b7546c1e9aaf525b1FA55","bridgeMediatorAddress":"0x397125902ED2cA2d42104F621f448A2cE1bC8Fb7","wormholeL2CoreAddress":"0xa321448d90d4e5b0A732867c18eA198e75CAC48E","wormholeL2TokenRelayerAddress":"0x796Dff6D74F3E27060B71255Fe517BFb23C93eed","wormholeL2MessageRelayer":"0x27428DD2d3DD32A4D7f7C497eAaa23130d894911","l1ChainId":"2","celoDepositProcessorL1Address":"0x223902b6C583f18E8dc84AF4E6a8fa523d088B78","celoTargetDispenserL2Address":"0xb4096d181C08DDF75f1A63918cCa0d1023C4e6C7"}
\ No newline at end of file
diff --git a/scripts/deployment/staking/wormhole/verify_05_celo_wormhole_target_dispenser.js b/scripts/deployment/staking/celo/verify_05_celo_target_dispenser.js
similarity index 100%
rename from scripts/deployment/staking/wormhole/verify_05_celo_wormhole_target_dispenser.js
rename to scripts/deployment/staking/celo/verify_05_celo_target_dispenser.js
diff --git a/scripts/deployment/staking/deploy_05_celo_wormhole_deposit_processor.js b/scripts/deployment/staking/deploy_05_celo_deposit_processor.js
similarity index 81%
rename from scripts/deployment/staking/deploy_05_celo_wormhole_deposit_processor.js
rename to scripts/deployment/staking/deploy_05_celo_deposit_processor.js
index 43d8d473..e1aab94e 100644
--- a/scripts/deployment/staking/deploy_05_celo_wormhole_deposit_processor.js
+++ b/scripts/deployment/staking/deploy_05_celo_deposit_processor.js
@@ -29,15 +29,15 @@ async function main() {
console.log("5. EOA to deploy WormholeDepositProcessorL1");
const WormholeDepositProcessorL1 = await ethers.getContractFactory("WormholeDepositProcessorL1");
console.log("You are signing the following transaction: WormholeDepositProcessorL1.connect(EOA).deploy()");
- const wormholeDepositProcessorL1 = await WormholeDepositProcessorL1.connect(EOA).deploy(parsedData.olasAddress,
+ const celoDepositProcessorL1 = await WormholeDepositProcessorL1.connect(EOA).deploy(parsedData.olasAddress,
parsedData.dispenserAddress, parsedData.wormholeL1TokenRelayerAddress,
parsedData.wormholeL1MessageRelayerAddress, parsedData.celoL2TargetChainId,
parsedData.wormholeL1CoreAddress, parsedData.celoWormholeL2TargetChainId);
- const result = await wormholeDepositProcessorL1.deployed();
+ const result = await celoDepositProcessorL1.deployed();
// Transaction details
console.log("Contract deployment: WormholeDepositProcessorL1");
- console.log("Contract address:", wormholeDepositProcessorL1.address);
+ console.log("Contract address:", celoDepositProcessorL1.address);
console.log("Transaction:", result.deployTransaction.hash);
// If on sepolia, wait a minute for the transaction completion
@@ -46,13 +46,13 @@ async function main() {
}
// Writing updated parameters back to the JSON file
- parsedData.wormholeDepositProcessorL1Address = wormholeDepositProcessorL1.address;
+ parsedData.celoDepositProcessorL1Address = celoDepositProcessorL1.address;
fs.writeFileSync(globalsFile, JSON.stringify(parsedData));
// Contract verification
if (parsedData.contractVerification) {
const execSync = require("child_process").execSync;
- execSync("npx hardhat verify --constructor-args scripts/deployment/staking/verify_05_wormhole_deposit_processor.js --network " + providerName + " " + wormholeDepositProcessorL1.address, { encoding: "utf-8" });
+ execSync("npx hardhat verify --constructor-args scripts/deployment/staking/verify_05_celo_deposit_processor.js --network " + providerName + " " + celoDepositProcessorL1.address, { encoding: "utf-8" });
}
}
diff --git a/scripts/deployment/staking/deploy_07_base_deposit_processor.js b/scripts/deployment/staking/deploy_07_base_deposit_processor.js
new file mode 100644
index 00000000..b2ce30d3
--- /dev/null
+++ b/scripts/deployment/staking/deploy_07_base_deposit_processor.js
@@ -0,0 +1,64 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+ let EOA;
+
+ const provider = await ethers.providers.getDefaultProvider(providerName);
+ const signers = await ethers.getSigners();
+
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Transaction signing and execution
+ console.log("7. EOA to deploy OptimismDepositProcessorL1 for Base");
+ const OptimismDepositProcessorL1 = await ethers.getContractFactory("OptimismDepositProcessorL1");
+ console.log("You are signing the following transaction: OptimismDepositProcessorL1.connect(EOA).deploy()");
+ const baseDepositProcessorL1 = await OptimismDepositProcessorL1.connect(EOA).deploy(parsedData.olasAddress,
+ parsedData.dispenserAddress, parsedData.baseL1StandardBridgeProxyAddress,
+ parsedData.baseL1CrossDomainMessengerProxyAddress, parsedData.baseL2TargetChainId,
+ parsedData.baseOLASAddress);
+ const result = await baseDepositProcessorL1.deployed();
+
+ // Transaction details
+ console.log("Contract deployment: OptimismDepositProcessorL1");
+ console.log("Contract address:", baseDepositProcessorL1.address);
+ console.log("Transaction:", result.deployTransaction.hash);
+
+ // If on sepolia, wait a minute for the transaction completion
+ if (providerName === "sepolia") {
+ await new Promise(r => setTimeout(r, 30000));
+ }
+
+ // Writing updated parameters back to the JSON file
+ parsedData.baseDepositProcessorL1Address = baseDepositProcessorL1.address;
+ fs.writeFileSync(globalsFile, JSON.stringify(parsedData));
+
+ // Contract verification
+ if (parsedData.contractVerification) {
+ const execSync = require("child_process").execSync;
+ execSync("npx hardhat verify --constructor-args scripts/deployment/staking/verify_07_base_deposit_processor.js --network " + providerName + " " + baseDepositProcessorL1.address, { encoding: "utf-8" });
+ }
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/deploy_08_ethereum_deposit_processor.js b/scripts/deployment/staking/deploy_08_ethereum_deposit_processor.js
new file mode 100644
index 00000000..7a7b3e8a
--- /dev/null
+++ b/scripts/deployment/staking/deploy_08_ethereum_deposit_processor.js
@@ -0,0 +1,62 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+ let EOA;
+
+ const provider = await ethers.providers.getDefaultProvider(providerName);
+ const signers = await ethers.getSigners();
+
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Transaction signing and execution
+ console.log("8. EOA to deploy EthereumDepositProcessor for Base");
+ const EthereumDepositProcessor = await ethers.getContractFactory("EthereumDepositProcessor");
+ console.log("You are signing the following transaction: EthereumDepositProcessor.connect(EOA).deploy()");
+ const ethereumDepositProcessor = await EthereumDepositProcessor.connect(EOA).deploy(parsedData.olasAddress,
+ parsedData.dispenserAddress, parsedData.serviceStakingFactoryAddress, parsedData.timelockAddress);
+ const result = await ethereumDepositProcessor.deployed();
+
+ // Transaction details
+ console.log("Contract deployment: EthereumDepositProcessor");
+ console.log("Contract address:", ethereumDepositProcessor.address);
+ console.log("Transaction:", result.deployTransaction.hash);
+
+ // If on sepolia, wait a minute for the transaction completion
+ if (providerName === "sepolia") {
+ await new Promise(r => setTimeout(r, 30000));
+ }
+
+ // Writing updated parameters back to the JSON file
+ parsedData.ethereumDepositProcessorAddress = ethereumDepositProcessor.address;
+ fs.writeFileSync(globalsFile, JSON.stringify(parsedData));
+
+ // Contract verification
+ if (parsedData.contractVerification) {
+ const execSync = require("child_process").execSync;
+ execSync("npx hardhat verify --constructor-args scripts/deployment/staking/verify_08_ethereum_deposit_processor.js --network " + providerName + " " + ethereumDepositProcessor.address, { encoding: "utf-8" });
+ }
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/deploy_09_set_targer_dispensers.js b/scripts/deployment/staking/deploy_09_set_targer_dispensers.js
new file mode 100644
index 00000000..95871b3e
--- /dev/null
+++ b/scripts/deployment/staking/deploy_09_set_targer_dispensers.js
@@ -0,0 +1,81 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+ const arbitrumDepositProcessorL1Address = parsedData.arbitrumDepositProcessorL1Address;
+ const arbitrumTargetDispenserL2Address = parsedData.arbitrumTargetDispenserL2Address;
+ const baseDepositProcessorL1Address = parsedData.baseDepositProcessorL1Address;
+ const baseTargetDispenserL2Address = parsedData.baseTargetDispenserL2Address;
+ const celoDepositProcessorL1Address = parsedData.celoDepositProcessorL1Address;
+ const celoTargetDispenserL2Address = parsedData.celoTargetDispenserL2Address;
+ const gnosisDepositProcessorL1Address = parsedData.gnosisDepositProcessorL1Address;
+ const gnosisTargetDispenserL2Address = parsedData.gnosisTargetDispenserL2Address;
+ const optimismDepositProcessorL1Address = parsedData.optimismDepositProcessorL1Address;
+ const optimismTargetDispenserL2Address = parsedData.optimismTargetDispenserL2Address;
+ const polygonDepositProcessorL1Address = parsedData.polygonDepositProcessorL1Address;
+ const polygonTargetDispenserL2Address = parsedData.polygonTargetDispenserL2Address;
+ let EOA;
+
+ const provider = await ethers.providers.getDefaultProvider(providerName);
+ const signers = await ethers.getSigners();
+
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Get all the contracts
+ const arbitrumDepositProcessorL1 = await ethers.getContractAt("ArbitrumDepositProcessorL1", arbitrumDepositProcessorL1Address);
+ const baseDepositProcessorL1 = await ethers.getContractAt("OptimismDepositProcessorL1", baseDepositProcessorL1Address);
+ const celoDepositProcessorL1 = await ethers.getContractAt("WormholeDepositProcessorL1", celoDepositProcessorL1Address);
+ const gnosisDepositProcessorL1 = await ethers.getContractAt("GnosisDepositProcessorL1", gnosisDepositProcessorL1Address);
+ const optimismDepositProcessorL1 = await ethers.getContractAt("OptimismDepositProcessorL1", optimismDepositProcessorL1Address);
+ const polygonDepositProcessorL1 = await ethers.getContractAt("PolygonDepositProcessorL1", polygonDepositProcessorL1Address);
+
+ // Transaction signing and execution
+ console.log("9. EOA to set TargetDispenserL2 in DepositProcessorL1-s");
+
+ console.log("You are signing the following transaction: ArbitrumDepositProcessorL1.connect(EOA).setL2TargetDispenser()");
+ let result = await arbitrumDepositProcessorL1.connect(EOA).setL2TargetDispenser(arbitrumTargetDispenserL2Address);
+ console.log("Transaction:", result.hash);
+
+ console.log("You are signing the following transaction: OptimismDepositProcessorL1.connect(EOA).setL2TargetDispenser()");
+ result = await baseDepositProcessorL1.connect(EOA).setL2TargetDispenser(baseTargetDispenserL2Address);
+ console.log("Transaction:", result.hash);
+
+ console.log("You are signing the following transaction: WormholeDepositProcessorL1.connect(EOA).setL2TargetDispenser()");
+ result = await celoDepositProcessorL1.connect(EOA).setL2TargetDispenser(celoTargetDispenserL2Address);
+ console.log("Transaction:", result.hash);
+
+ console.log("You are signing the following transaction: GnosisDepositProcessorL1.connect(EOA).setL2TargetDispenser()");
+ result = await gnosisDepositProcessorL1.connect(EOA).setL2TargetDispenser(gnosisTargetDispenserL2Address);
+ console.log("Transaction:", result.hash);
+
+ console.log("You are signing the following transaction: OptimismDepositProcessorL1.connect(EOA).setL2TargetDispenser()");
+ result = await optimismDepositProcessorL1.connect(EOA).setL2TargetDispenser(optimismTargetDispenserL2Address);
+ console.log("Transaction:", result.hash);
+
+ console.log("You are signing the following transaction: PolygonDepositProcessorL1.connect(EOA).setL2TargetDispenser()");
+ result = await polygonDepositProcessorL1.connect(EOA).setL2TargetDispenser(polygonTargetDispenserL2Address);
+ console.log("Transaction:", result.hash);
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/deploy_10_set_deposit_processors.js b/scripts/deployment/staking/deploy_10_set_deposit_processors.js
new file mode 100644
index 00000000..ddc68cff
--- /dev/null
+++ b/scripts/deployment/staking/deploy_10_set_deposit_processors.js
@@ -0,0 +1,62 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+ const arbitrumDepositProcessorL1Address = parsedData.arbitrumDepositProcessorL1Address;
+ const baseDepositProcessorL1Address = parsedData.baseDepositProcessorL1Address;
+ const celoDepositProcessorL1Address = parsedData.celoDepositProcessorL1Address;
+ const gnosisDepositProcessorL1Address = parsedData.gnosisDepositProcessorL1Address;
+ const optimismDepositProcessorL1Address = parsedData.optimismDepositProcessorL1Address;
+ const polygonDepositProcessorL1Address = parsedData.polygonDepositProcessorL1Address;
+ const ethereumDepositProcessorAddress = parsedData.ethereumDepositProcessorAddress;
+ const dispenserAddress = parsedData.dispenserAddress;
+ let EOA;
+
+ const provider = await ethers.providers.getDefaultProvider(providerName);
+ const signers = await ethers.getSigners();
+
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Get all the contracts
+ const arbitrumDepositProcessorL1 = await ethers.getContractAt("ArbitrumDepositProcessorL1", arbitrumDepositProcessorL1Address);
+ const baseDepositProcessorL1 = await ethers.getContractAt("OptimismDepositProcessorL1", baseDepositProcessorL1Address);
+ const celoDepositProcessorL1 = await ethers.getContractAt("WormholeDepositProcessorL1", celoDepositProcessorL1Address);
+ const gnosisDepositProcessorL1 = await ethers.getContractAt("GnosisDepositProcessorL1", gnosisDepositProcessorL1Address);
+ const optimismDepositProcessorL1 = await ethers.getContractAt("OptimismDepositProcessorL1", optimismDepositProcessorL1Address);
+ const polygonDepositProcessorL1 = await ethers.getContractAt("PolygonDepositProcessorL1", polygonDepositProcessorL1Address);
+ const dispenser = await ethers.getContractAt("Dispenser", dispenserAddress);
+
+ // Transaction signing and execution
+ console.log("10. EOA to set deposit processors in Dispenser");
+ console.log("You are signing the following transaction: Dispenser.connect(EOA).setDepositProcessorChainIds()");
+ const ethereumChainId = (await provider.getNetwork()).chainId;
+ const result = await dispenser.connect(EOA).setDepositProcessorChainIds([arbitrumDepositProcessorL1Address,
+ baseDepositProcessorL1Address, celoDepositProcessorL1Address, ethereumDepositProcessorAddress,
+ gnosisDepositProcessorL1Address, optimismDepositProcessorL1Address, polygonDepositProcessorL1Address],
+ [parsedData.arbitrumL2TargetChainId, parsedData.baseL2TargetChainId, parsedData.celoL2TargetChainId, ethereumChainId,
+ parsedData.gnosisL2TargetChainId, parsedData.optimisticL2TargetChainId, parsedData.polygonL2TargetChainId]);
+ console.log("Transaction:", result.hash);
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/globals_mainnet.json b/scripts/deployment/staking/globals_mainnet.json
new file mode 100644
index 00000000..f39c24d8
--- /dev/null
+++ b/scripts/deployment/staking/globals_mainnet.json
@@ -0,0 +1 @@
+{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"mainnet","olasAddress":"0x0001A500A6B18995B03f44bb040A5fFc28E45CB0","timelockAddress":"0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE","dispenserAddress":"0x5650300fCBab43A0D7D02F8Cb5d0f039402593f0","arbitrumL1ERC20GatewayRouterAddress":"0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef","arbitrumL1ERC20GatewayAddress":"0xa3A7B6F88361F48403514059F1F16C8E78d60EeC","arbitrumInboxAddress":"0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f","arbitrumOutboxAddress":"0x0B9857ae2D4A3DBe74ffE1d7DF045bb7F96E4840","arbitrumBridgeAddress":"0x8315177aB297bA92A06054cE80a67Ed4DBd7ed3a","arbitrumL2TargetChainId":"42161","arbitrumDepositProcessorL1Address":"0x5e13E07006D68B097DCb5979ef5545C4f9156162","gnosisOmniBridgeAddress":"0x88ad09518695c6c3712AC10a214bE5109a655671","gnosisAMBForeignAddress":"0x4C36d2919e407f0Cc2Ee3c993ccF8ac26d9CE64e","gnosisL2TargetChainId":"100","gnosisDepositProcessorL1Address":"0xEEf2c02cFC445bFFf1c891D486424Ef3aBc66AB0","optimisticL1StandardBridgeProxyAddress":"0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1","optimisticL1CrossDomainMessengerProxyAddress":"0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1","optimisticOLASAddress":"0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527","optimisticL2TargetChainId":"10","optimismDepositProcessorL1Address":"0xAB787ceebe8F2b8dca44e3bB744D6e63003ee978","wormholeL1CoreAddress":"0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B","wormholeL1TokenRelayerAddress":"0x3ee18B2214AFF97000D974cf647E7C347E8fa585","wormholeL1MessageRelayerAddress":"0x27428DD2d3DD32A4D7f7C497eAaa23130d894911","celoL2TargetChainId":"42220","celoWormholeL2TargetChainId":"14","celoDepositProcessorL1Address":"0x223902b6C583f18E8dc84AF4E6a8fa523d088B78","polygonRootChainManagerProxyAddress":"0xA0c68C638235ee32657e8f720a23ceC1bFc77C77","polygonFXRootAddress":"0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2","polygonCheckpointManagerAddress":"0x86E4Dc95c7FBdBf52e33D563BbDB00823894C287","polygonERC20PredicateAddress":"0x40ec5B33f54e0E8A33A975908C5BA1c14e5BbbDf","polygonL2TargetChainId":"137","polygonDepositProcessorL1Address":"0x4Ce43b82EF1298E1466D3b3Cee67BA6680bF82FB","baseL1StandardBridgeProxyAddress":"0x3154Cf16ccdb4C6d922629664174b904d80F2C35","baseL1CrossDomainMessengerProxyAddress":"0x866E82a600A1414e583f7F13623F1aC5d58b0Afa","baseOLASAddress":"0x54330d28ca3357F294334BDC454a032e7f353416","baseL2TargetChainId":"8453","baseDepositProcessorL1Address":"0x42BA1BbD797E4C90F386F03a544F3b62C1f917d0","serviceStakingFactoryAddress":"0xEBdde456EA288b49f7D5975E7659bA1Ccf607efc","ethereumDepositProcessorAddress":"0x15CD7fAeE048c7673aB818C9e582630F1a924593","arbitrumTargetDispenserL2Address":"0x10c5525F77F13b28f42c5626240c001c2D57CAd4","baseTargetDispenserL2Address":"0xcDdD9D9ABaB36fFa882530D69c73FeE5D4001C2d","celoTargetDispenserL2Address":"0xb4096d181C08DDF75f1A63918cCa0d1023C4e6C7","gnosisTargetDispenserL2Address":"0x67722c823010CEb4BED5325fE109196C0f67D053","optimismTargetDispenserL2Address":"0x04b0007b2aFb398015B76e5f22993a1fddF83644","polygonTargetDispenserL2Address":"0xf76953444C35F1FcE2F6CA1b167173357d3F5C17"}
\ No newline at end of file
diff --git a/scripts/deployment/staking/globals_sepolia.json b/scripts/deployment/staking/globals_sepolia.json
index 7b1f6dda..78d3a9ee 100644
--- a/scripts/deployment/staking/globals_sepolia.json
+++ b/scripts/deployment/staking/globals_sepolia.json
@@ -1 +1 @@
-{"contractVerification":true,"useLedger":false,"derivationPath":"m/44'/60'/2'/0/0","providerName":"sepolia","olasAddress":"0xeb2725bD76f6b1569Cf1484fCa0f2D55714A085d","dispenserAddress":"0x42f43be9E5E50df51b86C5c6427223ff565f40C6","arbitrumL1ERC20GatewayRouterAddress":"0xcE18836b233C83325Cc8848CA4487e94C6288264","arbitrumL1ERC20GatewayAddress":"0x902b3E5f8F19571859F4AB1003B960a5dF693aFF","arbitrumInboxAddress":"0xaAe29B0366299461418F5324a79Afc425BE5ae21","arbitrumOutboxAddress":"0x65f07C7D521164a4d5DaC6eB8Fac8DA067A3B78F","arbitrumBridgeAddress":"0x38f918D0E9F1b721EDaA41302E399fa1B79333a9","arbitrumL2TargetChainId":"421614","arbitrumDepositProcessorL1Address":"0xACd410f51DA5aAe1fF925565FBCB6B6eedbB00E2","gnosisOmniBridgeAddress":"0x63E47C5e3303DDDCaF3b404B1CCf9Eb633652e9e","gnosisAMBForeignAddress":"0xf2546D6648BD2af6a008A7e7C1542BB240329E11","gnosisL2TargetChainId":"10200","gnosisDepositProcessorL1Address":"0x679Ce81a7bab6808534137585850dc81F90Ea8a4","optimisticL1StandardBridgeProxyAddress":"0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1","optimisticL1CrossDomainMessengerProxyAddress":"0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef","optimisticOLASAddress":"0x01B8b6384298D4848E3BE63D4C9D17830EeE488A","optimisticL2TargetChainId":"11155420","optimismDepositProcessorL1Address":"0xDc6B77e32e751C7d6e1d1c39A64c64a8F0049E21","wormholeL1CoreAddress":"0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78","wormholeL1TokenRelayerAddress":"0xDB5492265f6038831E89f495670FF909aDe94bd9","wormholeL1MessageRelayerAddress":"0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470","celoL2TargetChainId":"44787","celoWormholeL2TargetChainId":"14","celoWormholeDepositProcessorL1Address":"","polygonRootChainManagerProxyAddress":"0x34F5A25B627f50Bb3f5cAb72807c4D4F405a9232","polygonFXRootAddress":"0x0E13EBEdDb8cf9f5987512d5E081FdC2F5b0991e","polygonCheckpointManagerAddress":"0xbd07D7E1E93c8d4b2a261327F3C28a8EA7167209","polygonERC20PredicateAddress":"0x4258c75b752c812b7fa586bdeb259f2d4bd17f4f","polygonL2TargetChainId":"80002","polygonDepositProcessorL1Address":"0x36c1beAFBeaf65DFcF16De60867BF9525455bf4E"}
\ No newline at end of file
+{"contractVerification":true,"useLedger":false,"derivationPath":"m/44'/60'/2'/0/0","providerName":"sepolia","olasAddress":"0xeb2725bD76f6b1569Cf1484fCa0f2D55714A085d","timelockAddress":"0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE","dispenserAddress":"0x42f43be9E5E50df51b86C5c6427223ff565f40C6","arbitrumL1ERC20GatewayRouterAddress":"0xcE18836b233C83325Cc8848CA4487e94C6288264","arbitrumL1ERC20GatewayAddress":"0x902b3E5f8F19571859F4AB1003B960a5dF693aFF","arbitrumInboxAddress":"0xaAe29B0366299461418F5324a79Afc425BE5ae21","arbitrumOutboxAddress":"0x65f07C7D521164a4d5DaC6eB8Fac8DA067A3B78F","arbitrumBridgeAddress":"0x38f918D0E9F1b721EDaA41302E399fa1B79333a9","arbitrumL2TargetChainId":"421614","arbitrumDepositProcessorL1Address":"0xACd410f51DA5aAe1fF925565FBCB6B6eedbB00E2","gnosisOmniBridgeAddress":"0x63E47C5e3303DDDCaF3b404B1CCf9Eb633652e9e","gnosisAMBForeignAddress":"0xf2546D6648BD2af6a008A7e7C1542BB240329E11","gnosisL2TargetChainId":"10200","gnosisDepositProcessorL1Address":"0x679Ce81a7bab6808534137585850dc81F90Ea8a4","optimisticL1StandardBridgeProxyAddress":"0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1","optimisticL1CrossDomainMessengerProxyAddress":"0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef","optimisticOLASAddress":"0x01B8b6384298D4848E3BE63D4C9D17830EeE488A","optimisticL2TargetChainId":"11155420","optimismDepositProcessorL1Address":"0xDc6B77e32e751C7d6e1d1c39A64c64a8F0049E21","wormholeL1CoreAddress":"0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78","wormholeL1TokenRelayerAddress":"0xDB5492265f6038831E89f495670FF909aDe94bd9","wormholeL1MessageRelayerAddress":"0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470","celoL2TargetChainId":"44787","celoWormholeL2TargetChainId":"14","celoWormholeDepositProcessorL1Address":"","polygonRootChainManagerProxyAddress":"0x34F5A25B627f50Bb3f5cAb72807c4D4F405a9232","polygonFXRootAddress":"0x0E13EBEdDb8cf9f5987512d5E081FdC2F5b0991e","polygonCheckpointManagerAddress":"0xbd07D7E1E93c8d4b2a261327F3C28a8EA7167209","polygonERC20PredicateAddress":"0x4258c75b752c812b7fa586bdeb259f2d4bd17f4f","polygonL2TargetChainId":"80002","polygonDepositProcessorL1Address":"0x36c1beAFBeaf65DFcF16De60867BF9525455bf4E","serviceStakingFactoryAddress":"0x01187451346d46D6fd2e6647a2980E0d6C06d4Da"}
\ No newline at end of file
diff --git a/scripts/deployment/staking/gnosis/deploy_031_change_owner.js b/scripts/deployment/staking/gnosis/deploy_031_change_owner.js
new file mode 100644
index 00000000..5170247f
--- /dev/null
+++ b/scripts/deployment/staking/gnosis/deploy_031_change_owner.js
@@ -0,0 +1,48 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+ const gnosisTargetDispenserL2Address = parsedData.gnosisTargetDispenserL2Address;
+ const bridgeMediatorAddress = parsedData.bridgeMediatorAddress;
+
+ let networkURL = parsedData.networkURL;
+ const provider = new ethers.providers.JsonRpcProvider(networkURL);
+ const signers = await ethers.getSigners();
+
+ let EOA;
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Transaction signing and execution
+ console.log("31. EOA to change owner in GnosisTargetDispenserL2");
+ const gnosisTargetDispenserL2 = await ethers.getContractAt("GnosisTargetDispenserL2", gnosisTargetDispenserL2Address);
+ console.log("You are signing the following transaction: GnosisTargetDispenserL2.connect(EOA).changeOwner()");
+ const result = await gnosisTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress);
+
+ // Transaction details
+ console.log("Contract deployment: GnosisTargetDispenserL2");
+ console.log("Contract address:", gnosisTargetDispenserL2.address);
+ console.log("Transaction:", result.hash);
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/gnosis/globals_gnosis_mainnet.json b/scripts/deployment/staking/gnosis/globals_gnosis_mainnet.json
new file mode 100644
index 00000000..8697e959
--- /dev/null
+++ b/scripts/deployment/staking/gnosis/globals_gnosis_mainnet.json
@@ -0,0 +1 @@
+{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"gnosis","networkURL":"https://rpc.gnosischain.com","gasPriceInGwei":"5","olasAddress":"0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f","serviceStakingFactoryAddress":"0xb0228CA253A88Bc8eb4ca70BCAC8f87b381f4700","bridgeMediatorAddress":"0x15bd56669F57192a97dF41A2aa8f4403e9491776","gnosisAMBHomeAddress":"0x75Df5AF045d91108662D8080fD1FEFAd6aA0bb59","l1ChainId":"1","gnosisDepositProcessorL1Address":"0xEEf2c02cFC445bFFf1c891D486424Ef3aBc66AB0","gnosisTargetDispenserL2Address":"0x67722c823010CEb4BED5325fE109196C0f67D053"}
\ No newline at end of file
diff --git a/scripts/deployment/staking/optimistic/deploy_41_change_owner.js b/scripts/deployment/staking/optimistic/deploy_41_change_owner.js
new file mode 100644
index 00000000..5213fc69
--- /dev/null
+++ b/scripts/deployment/staking/optimistic/deploy_41_change_owner.js
@@ -0,0 +1,48 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+ const optimismTargetDispenserL2Address = parsedData.optimismTargetDispenserL2Address;
+ const bridgeMediatorAddress = parsedData.bridgeMediatorAddress;
+
+ let networkURL = parsedData.networkURL;
+ const provider = new ethers.providers.JsonRpcProvider(networkURL);
+ const signers = await ethers.getSigners();
+
+ let EOA;
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Transaction signing and execution
+ console.log("41. EOA to change owner in OptimismTargetDispenserL2");
+ const optimismTargetDispenserL2 = await ethers.getContractAt("OptimismTargetDispenserL2", optimismTargetDispenserL2Address);
+ console.log("You are signing the following transaction: OptimismTargetDispenserL2.connect(EOA).changeOwner()");
+ const result = await optimismTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress);
+
+ // Transaction details
+ console.log("Contract deployment: OptimismTargetDispenserL2");
+ console.log("Contract address:", optimismTargetDispenserL2.address);
+ console.log("Transaction:", result.hash);
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/optimistic/globals_optimistic_mainnet.json b/scripts/deployment/staking/optimistic/globals_optimistic_mainnet.json
new file mode 100644
index 00000000..d8a04c79
--- /dev/null
+++ b/scripts/deployment/staking/optimistic/globals_optimistic_mainnet.json
@@ -0,0 +1 @@
+{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"optimistic","networkURL":"https://optimism.drpc.org","gasPriceInGwei":"2","olasAddress":"0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527","serviceStakingFactoryAddress":"0xa45E64d13A30a51b91ae0eb182e88a40e9b18eD8","bridgeMediatorAddress":"0x87c511c8aE3fAF0063b3F3CF9C6ab96c4AA5C60c","optimisticL2CrossDomainMessengerAddress":"0x4200000000000000000000000000000000000007","l1ChainId":"1","optimismDepositProcessorL1Address":"0xAB787ceebe8F2b8dca44e3bB744D6e63003ee978","optimismTargetDispenserL2Address":"0x04b0007b2aFb398015B76e5f22993a1fddF83644"}
\ No newline at end of file
diff --git a/scripts/deployment/staking/optimistic/send_tokens_and_message.js b/scripts/deployment/staking/optimistic/send_tokens_and_message.js
index cc8c1dc9..23433dd7 100644
--- a/scripts/deployment/staking/optimistic/send_tokens_and_message.js
+++ b/scripts/deployment/staking/optimistic/send_tokens_and_message.js
@@ -55,7 +55,7 @@ const main = async () => {
await tx.wait();
// tx back: https://sepolia-optimism.etherscan.io/tx/0x08ff60b3ef506e0f34e5941953608fa5bec1a13d7e0a175084245aa622edf7e0
- // tx result:
+ // tx result: https://sepolia.etherscan.io/tx/0xcd6ad253a6f869899f25f5d69d8261dbabd1fe49d9fce69cbcd3672064bb49dc
// https://docs.optimism.io/builders/app-developers/tutorials/cross-dom-solidity#interact-with-the-l2-greeter
// https://github.com/t4sk/notes/tree/main/op
diff --git a/scripts/deployment/staking/polygon/deploy_06_polygon_targer_dispenser.js b/scripts/deployment/staking/polygon/deploy_06_polygon_targer_dispenser.js
index 10b7f502..45cbeab6 100644
--- a/scripts/deployment/staking/polygon/deploy_06_polygon_targer_dispenser.js
+++ b/scripts/deployment/staking/polygon/deploy_06_polygon_targer_dispenser.js
@@ -48,7 +48,7 @@ async function main() {
const polygonTargetDispenserL2 = await PolygonTargetDispenserL2.connect(EOA).deploy(parsedData.olasAddress,
parsedData.serviceStakingFactoryAddress, parsedData.polygonFXChildAddress,
parsedData.polygonDepositProcessorL1Address, parsedData.l1ChainId, { gasPrice });
- const result = await polygonTargetDispenserL2.deployed();
+ let result = await polygonTargetDispenserL2.deployed();
// Transaction details
console.log("Contract deployment: PolygonTargetDispenserL2");
@@ -62,6 +62,10 @@ async function main() {
parsedData.polygonTargetDispenserL2Address = polygonTargetDispenserL2.address;
fs.writeFileSync(globalsFile, JSON.stringify(parsedData));
+ console.log("You are signing the following transaction: PolygonTargetDispenserL2.connect(EOA).setFxRootTunnel()");
+ result = await polygonTargetDispenserL2.setFxRootTunnel(parsedData.polygonDepositProcessorL1Address);
+ console.log("Transaction:", result.hash);
+
// Contract verification
if (parsedData.contractVerification) {
const execSync = require("child_process").execSync;
diff --git a/scripts/deployment/staking/polygon/deploy_61_change_owner.js b/scripts/deployment/staking/polygon/deploy_61_change_owner.js
new file mode 100644
index 00000000..7a15c82b
--- /dev/null
+++ b/scripts/deployment/staking/polygon/deploy_61_change_owner.js
@@ -0,0 +1,48 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+const { LedgerSigner } = require("@anders-t/ethers-ledger");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const useLedger = parsedData.useLedger;
+ const derivationPath = parsedData.derivationPath;
+ const providerName = parsedData.providerName;
+ const polygonTargetDispenserL2Address = parsedData.polygonTargetDispenserL2Address;
+ const bridgeMediatorAddress = parsedData.bridgeMediatorAddress;
+
+ let networkURL = parsedData.networkURL;
+ const provider = new ethers.providers.JsonRpcProvider(networkURL);
+ const signers = await ethers.getSigners();
+
+ let EOA;
+ if (useLedger) {
+ EOA = new LedgerSigner(provider, derivationPath);
+ } else {
+ EOA = signers[0];
+ }
+ // EOA address
+ const deployer = await EOA.getAddress();
+ console.log("EOA is:", deployer);
+
+ // Transaction signing and execution
+ console.log("61. EOA to change owner in PolygonTargetDispenserL2");
+ const polygonTargetDispenserL2 = await ethers.getContractAt("PolygonTargetDispenserL2", polygonTargetDispenserL2Address);
+ console.log("You are signing the following transaction: PolygonTargetDispenserL2.connect(EOA).changeOwner()");
+ const result = await polygonTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress);
+
+ // Transaction details
+ console.log("Contract deployment: PolygonTargetDispenserL2");
+ console.log("Contract address:", polygonTargetDispenserL2.address);
+ console.log("Transaction:", result.hash);
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/scripts/deployment/staking/polygon/globals_polygon_mainnet.json b/scripts/deployment/staking/polygon/globals_polygon_mainnet.json
new file mode 100644
index 00000000..41760b04
--- /dev/null
+++ b/scripts/deployment/staking/polygon/globals_polygon_mainnet.json
@@ -0,0 +1 @@
+{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"polygon","networkURL":"https://polygon-mainnet.g.alchemy.com/v2/","gasPriceInGwei":"5","olasAddress":"0xFEF5d947472e72Efbb2E388c730B7428406F2F95","serviceStakingFactoryAddress":"0x46C0D07F55d4F9B5Eed2Fc9680B5953e5fd7b461","bridgeMediatorAddress":"0x9338b5153AE39BB89f50468E608eD9d764B755fD","polygonFXChildAddress":"0x8397259c983751DAf40400790063935a11afa28a","l1ChainId":"1","polygonDepositProcessorL1Address":"0x4Ce43b82EF1298E1466D3b3Cee67BA6680bF82FB","polygonTargetDispenserL2Address":"0xf76953444C35F1FcE2F6CA1b167173357d3F5C17"}
\ No newline at end of file
diff --git a/scripts/deployment/staking/verify_05_wormhole_deposit_processor.js b/scripts/deployment/staking/verify_05_celo_deposit_processor.js
similarity index 100%
rename from scripts/deployment/staking/verify_05_wormhole_deposit_processor.js
rename to scripts/deployment/staking/verify_05_celo_deposit_processor.js
diff --git a/scripts/deployment/staking/verify_07_base_deposit_processor.js b/scripts/deployment/staking/verify_07_base_deposit_processor.js
new file mode 100644
index 00000000..c7855344
--- /dev/null
+++ b/scripts/deployment/staking/verify_07_base_deposit_processor.js
@@ -0,0 +1,13 @@
+const fs = require("fs");
+const globalsFile = "globals.json";
+const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+const parsedData = JSON.parse(dataFromJSON);
+
+module.exports = [
+ parsedData.olasAddress,
+ parsedData.dispenserAddress,
+ parsedData.baseL1StandardBridgeProxyAddress,
+ parsedData.baseL1CrossDomainMessengerProxyAddress,
+ parsedData.baseL2TargetChainId,
+ parsedData.baseOLASAddress
+];
\ No newline at end of file
diff --git a/scripts/deployment/staking/verify_08_ethereum_deposit_processor.js b/scripts/deployment/staking/verify_08_ethereum_deposit_processor.js
new file mode 100644
index 00000000..d1a3c206
--- /dev/null
+++ b/scripts/deployment/staking/verify_08_ethereum_deposit_processor.js
@@ -0,0 +1,11 @@
+const fs = require("fs");
+const globalsFile = "globals.json";
+const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+const parsedData = JSON.parse(dataFromJSON);
+
+module.exports = [
+ parsedData.olasAddress,
+ parsedData.dispenserAddress,
+ parsedData.serviceStakingFactoryAddress,
+ parsedData.timelockAddress
+];
\ No newline at end of file
diff --git a/scripts/deployment/staking/wormhole/bridge_new_token.js b/scripts/deployment/staking/wormhole/test/bridge_new_token.js
similarity index 100%
rename from scripts/deployment/staking/wormhole/bridge_new_token.js
rename to scripts/deployment/staking/wormhole/test/bridge_new_token.js
diff --git a/scripts/deployment/staking/wormhole/deploy_00_mock_olas_as_erc20_ownerless.js b/scripts/deployment/staking/wormhole/test/deploy_00_mock_olas_as_erc20_ownerless.js
similarity index 100%
rename from scripts/deployment/staking/wormhole/deploy_00_mock_olas_as_erc20_ownerless.js
rename to scripts/deployment/staking/wormhole/test/deploy_00_mock_olas_as_erc20_ownerless.js
diff --git a/scripts/deployment/staking/wormhole/deploy_01_mock_dispenser.js b/scripts/deployment/staking/wormhole/test/deploy_01_mock_dispenser.js
similarity index 94%
rename from scripts/deployment/staking/wormhole/deploy_01_mock_dispenser.js
rename to scripts/deployment/staking/wormhole/test/deploy_01_mock_dispenser.js
index a035270c..a7b7d733 100644
--- a/scripts/deployment/staking/wormhole/deploy_01_mock_dispenser.js
+++ b/scripts/deployment/staking/wormhole/test/deploy_01_mock_dispenser.js
@@ -63,7 +63,7 @@ async function main() {
// Contract verification
if (parsedData.contractVerification) {
const execSync = require("child_process").execSync;
- execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/verify_01_mock_dispenser.js --network " + providerName + " " + dispenser.address, { encoding: "utf-8" });
+ execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/test/verify_01_mock_dispenser.js --network " + providerName + " " + dispenser.address, { encoding: "utf-8" });
}
}
diff --git a/scripts/deployment/staking/wormhole/deploy_05_celo_wormhole_targer_dispenser.js b/scripts/deployment/staking/wormhole/test/deploy_05_celo_wormhole_targer_dispenser.js
similarity index 94%
rename from scripts/deployment/staking/wormhole/deploy_05_celo_wormhole_targer_dispenser.js
rename to scripts/deployment/staking/wormhole/test/deploy_05_celo_wormhole_targer_dispenser.js
index 3bb9c756..342a2bbd 100644
--- a/scripts/deployment/staking/wormhole/deploy_05_celo_wormhole_targer_dispenser.js
+++ b/scripts/deployment/staking/wormhole/test/deploy_05_celo_wormhole_targer_dispenser.js
@@ -64,7 +64,7 @@ async function main() {
// Contract verification
if (parsedData.contractVerification) {
const execSync = require("child_process").execSync;
- execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/verify_05_celo_wormhole_target_dispenser.js --network " + providerName + " " + wormholeTargetDispenserL2.address, { encoding: "utf-8" });
+ execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/test/verify_05_celo_wormhole_target_dispenser.js --network " + providerName + " " + wormholeTargetDispenserL2.address, { encoding: "utf-8" });
}
}
diff --git a/scripts/deployment/staking/wormhole/deploy_05_polygon_wormhole_deposit_processor.js b/scripts/deployment/staking/wormhole/test/deploy_05_polygon_wormhole_deposit_processor.js
similarity index 94%
rename from scripts/deployment/staking/wormhole/deploy_05_polygon_wormhole_deposit_processor.js
rename to scripts/deployment/staking/wormhole/test/deploy_05_polygon_wormhole_deposit_processor.js
index 3b2cc674..b3f41be9 100644
--- a/scripts/deployment/staking/wormhole/deploy_05_polygon_wormhole_deposit_processor.js
+++ b/scripts/deployment/staking/wormhole/test/deploy_05_polygon_wormhole_deposit_processor.js
@@ -64,7 +64,7 @@ async function main() {
// Contract verification
if (parsedData.contractVerification) {
const execSync = require("child_process").execSync;
- execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/verify_05_polygon_wormhole_deposit_processor.js --network " + providerName + " " + wormholeDepositProcessorL1.address, { encoding: "utf-8" });
+ execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/test/verify_05_polygon_wormhole_deposit_processor.js --network " + providerName + " " + wormholeDepositProcessorL1.address, { encoding: "utf-8" });
}
}
diff --git a/scripts/deployment/staking/wormhole/globals_celo_mainnet.json b/scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json
similarity index 100%
rename from scripts/deployment/staking/wormhole/globals_celo_mainnet.json
rename to scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json
diff --git a/scripts/deployment/staking/wormhole/globals_polygon_mainnet.json b/scripts/deployment/staking/wormhole/test/globals_polygon_mainnet.json
similarity index 100%
rename from scripts/deployment/staking/wormhole/globals_polygon_mainnet.json
rename to scripts/deployment/staking/wormhole/test/globals_polygon_mainnet.json
diff --git a/scripts/deployment/staking/wormhole/send_tokens_and_message.js b/scripts/deployment/staking/wormhole/test/send_tokens_and_message.js
similarity index 100%
rename from scripts/deployment/staking/wormhole/send_tokens_and_message.js
rename to scripts/deployment/staking/wormhole/test/send_tokens_and_message.js
diff --git a/scripts/deployment/staking/wormhole/verify_01_mock_dispenser.js b/scripts/deployment/staking/wormhole/test/verify_01_mock_dispenser.js
similarity index 100%
rename from scripts/deployment/staking/wormhole/verify_01_mock_dispenser.js
rename to scripts/deployment/staking/wormhole/test/verify_01_mock_dispenser.js
diff --git a/scripts/deployment/staking/wormhole/test/verify_05_celo_wormhole_target_dispenser.js b/scripts/deployment/staking/wormhole/test/verify_05_celo_wormhole_target_dispenser.js
new file mode 100644
index 00000000..3028f790
--- /dev/null
+++ b/scripts/deployment/staking/wormhole/test/verify_05_celo_wormhole_target_dispenser.js
@@ -0,0 +1,14 @@
+const fs = require("fs");
+const globalsFile = "globals.json";
+const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+const parsedData = JSON.parse(dataFromJSON);
+
+module.exports = [
+ parsedData.olasAddress,
+ parsedData.serviceStakingFactoryAddress,
+ parsedData.wormholeL2MessageRelayer,
+ parsedData.celoWormholeDepositProcessorL1Address,
+ parsedData.wormholel1ChainId,
+ parsedData.wormholeL2CoreAddress,
+ parsedData.wormholeL2TokenRelayerAddress
+];
\ No newline at end of file
diff --git a/scripts/deployment/staking/wormhole/verify_05_polygon_wormhole_deposit_processor.js b/scripts/deployment/staking/wormhole/test/verify_05_polygon_wormhole_deposit_processor.js
similarity index 100%
rename from scripts/deployment/staking/wormhole/verify_05_polygon_wormhole_deposit_processor.js
rename to scripts/deployment/staking/wormhole/test/verify_05_polygon_wormhole_deposit_processor.js
diff --git a/scripts/deployment/verify_07_dispenser.js b/scripts/deployment/verify_07_dispenser.js
index f8cc6de3..b5cdd7e7 100644
--- a/scripts/deployment/verify_07_dispenser.js
+++ b/scripts/deployment/verify_07_dispenser.js
@@ -4,8 +4,22 @@ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
const parsedData = JSON.parse(dataFromJSON);
const tokenomicsProxyAddress = parsedData.tokenomicsProxyAddress;
const treasuryAddress = parsedData.treasuryAddress;
+const olasAddress = parsedData.olasAddress;
+const voteWeightingAddress = parsedData.voteWeightingAddress;
+const retainerAddress = parsedData.retainerAddress;
+const maxNumClaimingEpochs = parsedData.maxNumClaimingEpochs;
+const maxNumStakingTargets = parsedData.maxNumStakingTargets;
+const minStakingWeight = parsedData.minStakingWeight;
+const maxStakingIncentive = parsedData.maxStakingIncentive;
module.exports = [
+ olasAddress,
tokenomicsProxyAddress,
- treasuryAddress
+ treasuryAddress,
+ voteWeightingAddress,
+ retainerAddress,
+ maxNumClaimingEpochs,
+ maxNumStakingTargets,
+ minStakingWeight,
+ maxStakingIncentive
];
\ No newline at end of file
diff --git a/scripts/proposals/proposal_09_change_dispenser_and_disable_previous_one.js b/scripts/proposals/proposal_09_change_dispenser_and_disable_previous_one.js
new file mode 100644
index 00000000..f3a93114
--- /dev/null
+++ b/scripts/proposals/proposal_09_change_dispenser_and_disable_previous_one.js
@@ -0,0 +1,69 @@
+/*global process*/
+
+const { ethers } = require("hardhat");
+
+async function main() {
+ const fs = require("fs");
+ const globalsFile = "globals.json";
+ const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
+ let parsedData = JSON.parse(dataFromJSON);
+ const providerName = parsedData.providerName;
+
+ const provider = await ethers.providers.getDefaultProvider(providerName);
+
+ // Get all the necessary contract addresses
+ const tokenomicsProxyAddress = parsedData.tokenomicsProxyAddress;
+ const treasuryAddress = parsedData.treasuryAddress;
+ const dispenserAddress = parsedData.dispenserAddress;
+ const arbitrumDepositProcessorL1Address = parsedData.arbitrumDepositProcessorL1Address;
+ const baseDepositProcessorL1Address = parsedData.baseDepositProcessorL1Address;
+ const celoDepositProcessorL1Address = parsedData.celoDepositProcessorL1Address;
+ const ethereumDepositProcessorAddress = parsedData.ethereumDepositProcessorAddress;
+ const gnosisDepositProcessorL1Address = parsedData.gnosisDepositProcessorL1Address;
+ const optimismDepositProcessorL1Address = parsedData.optimismDepositProcessorL1Address;
+ const polygonDepositProcessorL1Address = parsedData.polygonDepositProcessorL1Address;
+ const minStakingWeight = parsedData.minStakingWeight;
+ const maxStakingIncentive = parsedData.maxStakingIncentive;
+
+ // Get contract instances
+ const tokenomics = await ethers.getContractAt("Tokenomics", tokenomicsProxyAddress);
+ const treasury = await ethers.getContractAt("Treasury", treasuryAddress);
+
+ const oldDispenserAddress = "0xeED0000fE94d7cfeF4Dc0CA86a223f0F603A61B8";
+ const dispenserJSON = "abis/0.8.18/Dispenser.json";
+ const contractFromJSON = fs.readFileSync(dispenserJSON, "utf8");
+ const parsedFile = JSON.parse(contractFromJSON);
+ const abi = parsedFile["abi"];
+ const oldDispenser = new ethers.Contract(oldDispenserAddress, abi, provider);
+
+ const AddressZero = ethers.constants.AddressZero;
+ const AddressNull = "0x000000000000000000000000000000000000dEaD";
+
+ // Proposal preparation
+ console.log("Proposal 9. Change dispenser address in tokenomics and treasury, disable old Dispenser");
+ const targets = [tokenomicsProxyAddress, tokenomicsProxyAddress, treasuryAddress, oldDispenserAddress,
+ oldDispenserAddress];
+ const values = [0, 0, 0, 0, 0];
+ const callDatas = [
+ tokenomics.interface.encodeFunctionData("changeManagers", [AddressZero, AddressZero, dispenserAddress]),
+ tokenomics.interface.encodeFunctionData("changeStakingParams", [maxStakingIncentive, minStakingWeight]),
+ treasury.interface.encodeFunctionData("changeManagers", [AddressZero, AddressZero, dispenserAddress]),
+ oldDispenser.interface.encodeFunctionData("changeManagers", [AddressNull, AddressNull]),
+ oldDispenser.interface.encodeFunctionData("changeOwner", [AddressNull])
+ ];
+
+ const description = "Change Dispenser address in Tokenomics and Treasury, disable old Dispenser";
+
+ // Proposal details
+ console.log("targets:", targets);
+ console.log("values:", values);
+ console.log("call datas:", callDatas);
+ console.log("description:", description);
+}
+
+main()
+ .then(() => process.exit(0))
+ .catch((error) => {
+ console.error(error);
+ process.exit(1);
+ });
diff --git a/test/Depository.t.sol b/test/Depository.t.sol
index 0036156a..4971f5b2 100644
--- a/test/Depository.t.sol
+++ b/test/Depository.t.sol
@@ -6,8 +6,9 @@ import {ZuniswapV2Factory} from "zuniswapv2/ZuniswapV2Factory.sol";
import {ZuniswapV2Router} from "zuniswapv2/ZuniswapV2Router.sol";
import {ZuniswapV2Pair} from "zuniswapv2/ZuniswapV2Pair.sol";
import {Depository} from "../contracts/Depository.sol";
-import {GenericBondCalculator} from "../contracts/GenericBondCalculator.sol";
+import {BondCalculator, DiscountParams} from "../contracts/BondCalculator.sol";
import {MockTokenomics} from "../contracts/test/MockTokenomics.sol";
+import {MockVE} from "../contracts/test/MockVE.sol";
import {Treasury} from "../contracts/Treasury.sol";
import {MockERC20} from "../lib/zuniswapv2/lib/solmate/src/test/utils/mocks/MockERC20.sol";
@@ -20,7 +21,8 @@ contract BaseSetup is Test {
MockTokenomics internal tokenomics;
Treasury internal treasury;
Depository internal depository;
- GenericBondCalculator internal genericBondCalculator;
+ BondCalculator internal bondCalculator;
+ MockVE internal ve;
address payable[] internal users;
address internal deployer;
@@ -56,11 +58,16 @@ contract BaseSetup is Test {
tokenomics = new MockTokenomics();
// Correct depository address is missing here, it will be defined just one line below
treasury = new Treasury(address(olas), address(tokenomics), deployer, deployer);
- // Deploy generic bond calculator contract
- genericBondCalculator = new GenericBondCalculator(address(olas), address(tokenomics));
+ // veOLAS
+ ve = new MockVE();
+ // Deploy bond calculator contract
+ DiscountParams memory discountParams;
+ discountParams.targetVotingPower = 10 ether;
+ discountParams.targetNewUnits = 10;
+ bondCalculator = new BondCalculator(address(olas), address(tokenomics), address(ve), discountParams);
// Deploy depository contract
depository = new Depository("Depository", "OLAS_BOND", "baseURI", address(olas), address(tokenomics),
- address(treasury), address(genericBondCalculator));
+ address(treasury), address(bondCalculator));
// Change depository contract addresses to the correct ones
treasury.changeManagers(address(0), address(depository), address(0));
diff --git a/test/Depository2BondCalculator.js b/test/Depository2BondCalculator.js
index 37004f6c..6c49513d 100644
--- a/test/Depository2BondCalculator.js
+++ b/test/Depository2BondCalculator.js
@@ -264,6 +264,10 @@ describe("Depository LP 2 Bond Calculator", async () => {
defaultDiscountParams.weightFactors[3] = 1000;
// Now able to change discount params
await bondCalculator.changeDiscountParams(defaultDiscountParams);
+
+
+ const checkDiscountParams = await bondCalculator.getDiscountParams();
+ expect(checkDiscountParams.weightFactors[3]).to.equal(defaultDiscountParams.weightFactors[3]);
});
});
diff --git a/test/Depository2GenericBondCalculator.js b/test/Depository2GenericBondCalculator.js
index 1f0ae270..91f14ce4 100644
--- a/test/Depository2GenericBondCalculator.js
+++ b/test/Depository2GenericBondCalculator.js
@@ -18,7 +18,7 @@ describe("Depository LP 2 Generic Bond Calculator", async () => {
let olasFactory;
let depositoryFactory;
let tokenomicsFactory;
- let genericBondCalculator;
+ let bondCalculator;
let router;
let factory;
@@ -29,6 +29,7 @@ describe("Depository LP 2 Generic Bond Calculator", async () => {
let treasury;
let treasuryFactory;
let tokenomics;
+ let ve;
let epochLen = 86400 * 10;
let defaultPriceLP = "2" + decimals;
@@ -40,10 +41,16 @@ describe("Depository LP 2 Generic Bond Calculator", async () => {
let vesting = oneWeek;
- var productId = 0;
+ let productId = 0;
let first;
let id;
+ const discountParams = {
+ targetVotingPower: ethers.utils.parseEther("10"),
+ targetNewUnits: 10,
+ weightFactors: new Array(4).fill(0)
+ };
+
let attackDepositFactory;
let attackDeposit;
@@ -64,22 +71,28 @@ describe("Depository LP 2 Generic Bond Calculator", async () => {
dai = await erc20Token.deploy();
olas = await olasFactory.deploy();
+
+ // Voting Escrow mock
+ const VE = await ethers.getContractFactory("MockVE");
+ ve = await VE.deploy();
+ await ve.deployed();
+
// Correct treasury address is missing here, it will be defined just one line below
tokenomics = await tokenomicsFactory.deploy();
await tokenomics.initializeTokenomics(olas.address, deployer.address, deployer.address, deployer.address,
- deployer.address, epochLen, deployer.address, deployer.address, deployer.address, AddressZero);
+ ve.address, epochLen, deployer.address, deployer.address, deployer.address, AddressZero);
// Correct depository address is missing here, it will be defined just one line below
treasury = await treasuryFactory.deploy(olas.address, tokenomics.address, deployer.address, deployer.address);
// Change bond fraction to 100% in these tests
await tokenomics.changeIncentiveFractions(66, 34, 100, 0, 0, 0);
// Deploy generic bond calculator contract
- const GenericBondCalculator = await ethers.getContractFactory("GenericBondCalculator");
- genericBondCalculator = await GenericBondCalculator.deploy(olas.address, tokenomics.address);
- await genericBondCalculator.deployed();
+ const BondCalculator = await ethers.getContractFactory("BondCalculator");
+ bondCalculator = await BondCalculator.deploy(olas.address, tokenomics.address, ve.address, discountParams);
+ await bondCalculator.deployed();
// Deploy depository contract
depository = await depositoryFactory.deploy("Depository", "OLAS_BOND", baseURI, olas.address,
- tokenomics.address, treasury.address, genericBondCalculator.address);
+ tokenomics.address, treasury.address, bondCalculator.address);
// Deploy Attack example
attackDeposit = await attackDepositFactory.deploy();
@@ -220,7 +233,7 @@ describe("Depository LP 2 Generic Bond Calculator", async () => {
// Trying to change bond calculator to a zero address that results in no change
await depository.connect(deployer).changeBondCalculator(AddressZero);
- expect(await depository.bondCalculator()).to.equal(genericBondCalculator.address);
+ expect(await depository.bondCalculator()).to.equal(bondCalculator.address);
// Change bond calculator address
await depository.connect(deployer).changeBondCalculator(account.address);
diff --git a/test/DepositoryGenericBondCalculator.js b/test/DepositoryGenericBondCalculator.js
index 22082e6a..666ac7d2 100644
--- a/test/DepositoryGenericBondCalculator.js
+++ b/test/DepositoryGenericBondCalculator.js
@@ -18,7 +18,7 @@ describe("Depository LP Generic Bond Calculator", async () => {
let olasFactory;
let depositoryFactory;
let tokenomicsFactory;
- let genericBondCalculator;
+ let bondCalculator;
let router;
let factory;
@@ -29,6 +29,7 @@ describe("Depository LP Generic Bond Calculator", async () => {
let treasury;
let treasuryFactory;
let tokenomics;
+ let ve;
let epochLen = 86400 * 10;
let defaultPriceLP = "2" + decimals;
@@ -45,6 +46,12 @@ describe("Depository LP Generic Bond Calculator", async () => {
let first;
let id;
+ const discountParams = {
+ targetVotingPower: ethers.utils.parseEther("10"),
+ targetNewUnits: 10,
+ weightFactors: new Array(4).fill(0)
+ };
+
let attackDepositFactory;
let attackDeposit;
@@ -65,22 +72,28 @@ describe("Depository LP Generic Bond Calculator", async () => {
dai = await erc20Token.deploy();
olas = await olasFactory.deploy();
+
+ // Voting Escrow mock
+ const VE = await ethers.getContractFactory("MockVE");
+ ve = await VE.deploy();
+ await ve.deployed();
+
// Correct treasury address is missing here, it will be defined just one line below
tokenomics = await tokenomicsFactory.deploy();
await tokenomics.initializeTokenomics(olas.address, deployer.address, deployer.address, deployer.address,
- deployer.address, epochLen, deployer.address, deployer.address, deployer.address, AddressZero);
+ ve.address, epochLen, deployer.address, deployer.address, deployer.address, AddressZero);
// Correct depository address is missing here, it will be defined just one line below
treasury = await treasuryFactory.deploy(olas.address, tokenomics.address, deployer.address, deployer.address);
// Change bond fraction to 100% in these tests
await tokenomics.changeIncentiveFractions(66, 34, 100, 0, 0, 0);
// Deploy generic bond calculator contract
- const GenericBondCalculator = await ethers.getContractFactory("GenericBondCalculator");
- genericBondCalculator = await GenericBondCalculator.deploy(olas.address, tokenomics.address);
- await genericBondCalculator.deployed();
+ const BondCalculator = await ethers.getContractFactory("BondCalculator");
+ bondCalculator = await BondCalculator.deploy(olas.address, tokenomics.address, ve.address, discountParams);
+ await bondCalculator.deployed();
// Deploy depository contract
depository = await depositoryFactory.deploy("Depository", "OLAS_BOND", baseURI, olas.address,
- tokenomics.address, treasury.address, genericBondCalculator.address);
+ tokenomics.address, treasury.address, bondCalculator.address);
// Deploy Attack example
attackDeposit = await attackDepositFactory.deploy();
@@ -242,7 +255,7 @@ describe("Depository LP Generic Bond Calculator", async () => {
// Trying to change bond calculator to a zero address that results in no change
await depository.connect(deployer).changeBondCalculator(AddressZero);
- expect(await depository.bondCalculator()).to.equal(genericBondCalculator.address);
+ expect(await depository.bondCalculator()).to.equal(bondCalculator.address);
// Change bond calculator address
await depository.connect(deployer).changeBondCalculator(account.address);
@@ -250,13 +263,13 @@ describe("Depository LP Generic Bond Calculator", async () => {
});
it("Should fail if any of bond calculator input addresses is a zero address", async function () {
- const GenericBondCalculator = await ethers.getContractFactory("GenericBondCalculator");
+ const BondCalculator = await ethers.getContractFactory("BondCalculator");
await expect(
- GenericBondCalculator.deploy(AddressZero, tokenomics.address)
- ).to.be.revertedWithCustomError(genericBondCalculator, "ZeroAddress");
+ BondCalculator.deploy(AddressZero, tokenomics.address, AddressZero, discountParams)
+ ).to.be.revertedWithCustomError(bondCalculator, "ZeroAddress");
await expect(
- GenericBondCalculator.deploy(olas.address, AddressZero)
- ).to.be.revertedWithCustomError(genericBondCalculator, "ZeroAddress");
+ BondCalculator.deploy(olas.address, AddressZero, AddressZero, discountParams)
+ ).to.be.revertedWithCustomError(bondCalculator, "ZeroAddress");
});
});
@@ -920,7 +933,7 @@ describe("Depository LP Generic Bond Calculator", async () => {
// Now change the depository contract address
const newDepository = await depositoryFactory.deploy("Depository", "OLAS_BOND", baseURI, olas.address,
- tokenomics.address, treasury.address, genericBondCalculator.address);
+ tokenomics.address, treasury.address, bondCalculator.address);
// Change to a new depository address
await treasury.changeManagers(AddressZero, newDepository.address, AddressZero);
diff --git a/test/Dispenser.t.sol b/test/Dispenser.t.sol
index d9a12bfb..da8c5918 100644
--- a/test/Dispenser.t.sol
+++ b/test/Dispenser.t.sol
@@ -33,6 +33,7 @@ contract BaseSetup is Test {
uint256 internal initialMint = 10_000_000_000e18;
uint256 internal largeApproval = 1_000_000_000_000e18;
uint256 epochLen = 30 days;
+ uint256 delta = 100;
function setUp() public virtual {
emptyArray = new uint256[](0);
@@ -106,8 +107,8 @@ contract DispenserTest is BaseSetup {
assertEq(reward, 0);
assertEq(topUp, 0);
- // Lock OLAS balances with Voting Escrow
- ve.setWeightedBalance(tokenomics.veOLASThreshold());
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ ve.setWeightedBalance(tokenomics.inflationPerSecond() * 365 days);
ve.createLock(deployer);
// Change the first service owner to the deployer (same for components and agents)
@@ -173,20 +174,20 @@ contract DispenserTest is BaseSetup {
balanceETH = address(deployer).balance - balanceETH;
balanceOLAS = olas.balanceOf(deployer) - balanceOLAS;
assertEq(balanceETH, accountRewards);
- assertEq(balanceOLAS, accountTopUps);
+ assertLt(accountTopUps - balanceOLAS, delta);
}
/// @dev Deposit incentives for 2 services in a loop to go through a specified amount of time.
/// @notice Assume that no single donation is bigger than 2^64 - 1.
/// @param amount0 Amount to donate to the first service.
/// @param amount1 Amount to donate to the second service.
- function testIncentivesLoopDirect(uint64 amount0, uint64 amount1) public {
+ function testLoopDirectIncentives(uint64 amount0, uint64 amount1) public {
// Amounts must be meaningful
vm.assume(amount0 > treasury.minAcceptedETH());
vm.assume(amount1 > treasury.minAcceptedETH());
- // Lock OLAS balances with Voting Escrow
- ve.setWeightedBalance(tokenomics.veOLASThreshold());
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ ve.setWeightedBalance(tokenomics.getInflationForYear(4));
ve.createLock(deployer);
// Change the first service owner to the deployer (same for components and agents)
@@ -264,7 +265,7 @@ contract DispenserTest is BaseSetup {
balanceETH = address(deployer).balance - balanceETH;
balanceOLAS = olas.balanceOf(deployer) - balanceOLAS;
assertEq(balanceETH, accountRewards);
- assertEq(balanceOLAS, accountTopUps);
+ assertLt(accountTopUps - balanceOLAS, delta);
}
}
@@ -277,8 +278,8 @@ contract DispenserTest is BaseSetup {
vm.assume(amount0 > treasury.minAcceptedETH());
vm.assume(amount1 > treasury.minAcceptedETH());
- // Lock OLAS balances with Voting Escrow
- ve.setWeightedBalance(tokenomics.veOLASThreshold());
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ ve.setWeightedBalance(tokenomics.getInflationForYear(4));
ve.createLock(deployer);
// Change the first service owner to the deployer (same for components and agents)
@@ -341,7 +342,7 @@ contract DispenserTest is BaseSetup {
balanceETH = address(deployer).balance - balanceETH;
balanceOLAS = olas.balanceOf(deployer) - balanceOLAS;
assertEq(balanceETH, accountRewards);
- assertEq(balanceOLAS, accountTopUps);
+ assertLt(accountTopUps - balanceOLAS, delta);
// Zero previously calculated rewards and top-ups
rewards[0] = 0;
diff --git a/test/DispenserDevIncentives.js b/test/DispenserDevIncentives.js
index fecbf5f0..e3a20d79 100644
--- a/test/DispenserDevIncentives.js
+++ b/test/DispenserDevIncentives.js
@@ -225,12 +225,11 @@ describe("DispenserDevIncentives", async () => {
await helpers.time.increase(epochLen + 10);
await tokenomics.connect(deployer).checkpoint();
- // Get tokenomcis parameters from the previous epoch
+ // Get tokenomics parameters from the previous epoch
let lastPoint = Number(await tokenomics.epochCounter()) - 1;
// Get the epoch point of the last epoch
let ep = await tokenomics.mapEpochTokenomics(lastPoint);
expect(await tokenomics.devsPerCapital()).to.greaterThan(0);
- expect(ep.idf).to.greaterThan(0);
// Get the unit points of the last epoch
let up = [await tokenomics.getUnitPoint(lastPoint, 0), await tokenomics.getUnitPoint(lastPoint, 1)];
expect(up[0].rewardUnitFraction + up[1].rewardUnitFraction + ep.rewardTreasuryFraction).to.equal(100);
@@ -260,6 +259,121 @@ describe("DispenserDevIncentives", async () => {
// Start new epoch and calculate tokenomics parameters and rewards
await tokenomics.connect(deployer).checkpoint();
+ // Get the last settled epoch counter
+ lastPoint = Number(await tokenomics.epochCounter()) - 1;
+ // Get the epoch point of the last epoch
+ ep = await tokenomics.mapEpochTokenomics(lastPoint);
+ // Get the unit points of the last epoch
+ up = [await tokenomics.getUnitPoint(lastPoint, 0), await tokenomics.getUnitPoint(lastPoint, 1)];
+ // Calculate rewards based on the points information
+ const percentFraction = ethers.BigNumber.from(100);
+ let rewards = [
+ ethers.BigNumber.from(ep.totalDonationsETH).mul(ethers.BigNumber.from(up[0].rewardUnitFraction)).div(percentFraction),
+ ethers.BigNumber.from(ep.totalDonationsETH).mul(ethers.BigNumber.from(up[1].rewardUnitFraction)).div(percentFraction)
+ ];
+ let accountRewards = rewards[0].add(rewards[1]);
+ expect(accountRewards).to.greaterThan(0);
+
+ // Since minWeightedBalance < top-ups inflation per epoch, the max top-ups can be equal to minWeightedBalance
+ let accountTopUps = minWeightedBalance;
+ expect(accountTopUps).to.greaterThan(0);
+
+ // Check for the incentive balances of component and agent such that their pending relative incentives are non-zero
+ let incentiveBalances = await tokenomics.mapUnitIncentives(0, 1);
+ expect(Number(incentiveBalances.pendingRelativeReward)).to.greaterThan(0);
+ expect(Number(incentiveBalances.pendingRelativeTopUp)).to.greaterThan(0);
+ incentiveBalances = await tokenomics.mapUnitIncentives(1, 1);
+ expect(incentiveBalances.pendingRelativeReward).to.greaterThan(0);
+ expect(incentiveBalances.pendingRelativeTopUp).to.greaterThan(0);
+
+ // Get deployer incentives information
+ const result = await tokenomics.getOwnerIncentives(deployer.address, [0, 1], [1, 1]);
+ // Get accumulated rewards and top-ups
+ const checkedReward = ethers.BigNumber.from(result.reward);
+ const checkedTopUp = ethers.BigNumber.from(result.topUp);
+ // Check if they match with what was written to the tokenomics point with owner reward and top-up fractions
+ // Theoretical values must always be bigger than calculated ones (since round-off error is due to flooring)
+ expect(Math.abs(Number(accountRewards.sub(checkedReward)))).to.lessThan(delta);
+ expect(Math.abs(Number(accountTopUps.sub(checkedTopUp)))).to.lessThan(delta);
+
+ // Simulate claiming rewards and top-ups for owners and check their correctness
+ const claimedOwnerIncentives = await dispenser.connect(deployer).callStatic.claimOwnerIncentives([0, 1], [1, 1]);
+ // Get accumulated rewards and top-ups
+ let claimedReward = ethers.BigNumber.from(claimedOwnerIncentives.reward);
+ let claimedTopUp = ethers.BigNumber.from(claimedOwnerIncentives.topUp);
+
+ // Check if they match with what was written to the tokenomics point with owner reward and top-up fractions
+ expect(claimedReward).to.lessThanOrEqual(accountRewards);
+ expect(Math.abs(Number(accountRewards.sub(claimedReward)))).to.lessThan(delta);
+ expect(claimedTopUp).to.lessThanOrEqual(accountTopUps);
+ expect(Math.abs(Number(accountTopUps.sub(claimedTopUp)))).to.lessThan(delta);
+
+ // Claim rewards and top-ups
+ const balanceBeforeTopUps = ethers.BigNumber.from(await olas.balanceOf(deployer.address));
+ await dispenser.connect(deployer).claimOwnerIncentives([0, 1], [1, 1]);
+ const balanceAfterTopUps = ethers.BigNumber.from(await olas.balanceOf(deployer.address));
+
+ // Check the OLAS balance after receiving incentives
+ const balance = balanceAfterTopUps.sub(balanceBeforeTopUps);
+ expect(balance).to.lessThanOrEqual(accountTopUps);
+ expect(Math.abs(Number(accountTopUps.sub(balance)))).to.lessThan(delta);
+
+ // Restore to the state of the snapshot
+ await snapshot.restore();
+ });
+
+ it("Claim incentives for unit owners with donation voting power bigger than the inflation", async () => {
+ // Take a snapshot of the current state of the blockchain
+ const snapshot = await helpers.takeSnapshot();
+
+ // Try to claim empty incentives
+ await expect(
+ dispenser.connect(deployer).claimOwnerIncentives([], [])
+ ).to.be.revertedWithCustomError(dispenser, "ClaimIncentivesFailed");
+
+ // Try to claim incentives for non-existent components
+ await expect(
+ dispenser.connect(deployer).claimOwnerIncentives([0], [0])
+ ).to.be.revertedWithCustomError(tokenomics, "WrongUnitId");
+
+ // Skip the number of seconds for 2 epochs
+ await helpers.time.increase(epochLen + 10);
+ await tokenomics.connect(deployer).checkpoint();
+
+ // Get tokenomics parameters from the previous epoch
+ let lastPoint = Number(await tokenomics.epochCounter()) - 1;
+ // Get the epoch point of the last epoch
+ let ep = await tokenomics.mapEpochTokenomics(lastPoint);
+ expect(await tokenomics.devsPerCapital()).to.greaterThan(0);
+ // Get the unit points of the last epoch
+ let up = [await tokenomics.getUnitPoint(lastPoint, 0), await tokenomics.getUnitPoint(lastPoint, 1)];
+ expect(up[0].rewardUnitFraction + up[1].rewardUnitFraction + ep.rewardTreasuryFraction).to.equal(100);
+
+ await helpers.time.increase(epochLen + 10);
+ await tokenomics.connect(deployer).checkpoint();
+
+ // Send ETH to treasury
+ const amount = ethers.utils.parseEther("1000");
+ await deployer.sendTransaction({to: treasury.address, value: amount});
+
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ const inflationPerYear = await tokenomics.getInflationForYear(0);
+ await ve.setWeightedBalance(inflationPerYear.toString());
+ await ve.createLock(deployer.address);
+
+ // Change the first service owner to the deployer (same for components and agents)
+ await serviceRegistry.changeUnitOwner(1, deployer.address);
+ await componentRegistry.changeUnitOwner(1, deployer.address);
+ await agentRegistry.changeUnitOwner(1, deployer.address);
+
+ // Send donations to services
+ await treasury.connect(deployer).depositServiceDonationsETH([1, 2], [regDepositFromServices, regDepositFromServices],
+ {value: twoRegDepositFromServices});
+ // Move more than one epoch in time
+ await helpers.time.increase(epochLen + 10);
+ // Start new epoch and calculate tokenomics parameters and rewards
+ await tokenomics.connect(deployer).checkpoint();
+
// Get the last settled epoch counter
lastPoint = Number(await tokenomics.epochCounter()) - 1;
// Get the epoch point of the last epoch
@@ -344,12 +458,11 @@ describe("DispenserDevIncentives", async () => {
await helpers.time.increase(epochLen + 10);
await tokenomics.connect(deployer).checkpoint();
- // Get tokenomcis parameters from the previous epoch
+ // Get tokenomics parameters from the previous epoch
let lastPoint = Number(await tokenomics.epochCounter()) - 1;
// Get the epoch point of the last epoch
let ep = await tokenomics.mapEpochTokenomics(lastPoint);
expect(await tokenomics.devsPerCapital()).to.greaterThan(0);
- expect(ep.idf).to.greaterThan(0);
// Get the unit points of the last epoch
let up = [await tokenomics.getUnitPoint(lastPoint, 0), await tokenomics.getUnitPoint(lastPoint, 1)];
expect(up[0].rewardUnitFraction + up[1].rewardUnitFraction + ep.rewardTreasuryFraction).to.equal(100);
@@ -361,9 +474,9 @@ describe("DispenserDevIncentives", async () => {
const amount = ethers.utils.parseEther("1000");
await deployer.sendTransaction({to: treasury.address, value: amount});
- // Lock OLAS balances with Voting Escrow
- const minWeightedBalance = await tokenomics.veOLASThreshold();
- await ve.setWeightedBalance(minWeightedBalance.toString());
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ const inflationPerYear = await tokenomics.getInflationForYear(0);
+ await ve.setWeightedBalance(inflationPerYear.toString());
await ve.createLock(signers[1].address);
// Change the first service owner to the deployer (same for components and agents)
@@ -508,9 +621,10 @@ describe("DispenserDevIncentives", async () => {
expect(checkedTopUp).to.equal(0);
// EPOCH 2 with donations and top-ups
- // Return the ability for the service owner to have enough veOLAS for the owner top-ups
- const minWeightedBalance = await tokenomics.veOLASThreshold();
- await ve.setWeightedBalance(minWeightedBalance.toString());
+ // Return the ability to donate
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ const inflationPerYear = await tokenomics.getInflationForYear(0);
+ await ve.setWeightedBalance(inflationPerYear.toString());
await ve.createLock(deployer.address);
// Increase the time to more than the length of the epoch
@@ -592,9 +706,9 @@ describe("DispenserDevIncentives", async () => {
await helpers.time.increase(epochLen + 10);
await tokenomics.connect(deployer).checkpoint();
- // Lock OLAS balances with Voting Escrow
- const minWeightedBalance = await tokenomics.veOLASThreshold();
- await ve.setWeightedBalance(minWeightedBalance.toString());
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ const inflationPerYear = await tokenomics.getInflationForYear(0);
+ await ve.setWeightedBalance(inflationPerYear.toString());
await ve.createLock(deployer.address);
let totalAccountTopUps = ethers.BigNumber.from(0);
@@ -668,9 +782,9 @@ describe("DispenserDevIncentives", async () => {
const amount = ethers.utils.parseEther("1000");
await deployer.sendTransaction({to: treasury.address, value: amount});
- // Lock OLAS balances with Voting Escrow
- const minWeightedBalance = await tokenomics.veOLASThreshold();
- await ve.setWeightedBalance(minWeightedBalance.toString());
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ const inflationPerYear = await tokenomics.getInflationForYear(0);
+ await ve.setWeightedBalance(inflationPerYear.toString());
await ve.createLock(deployer.address);
// Change the first service owner to the deployer (same for components and agents)
@@ -767,9 +881,9 @@ describe("DispenserDevIncentives", async () => {
const amount = ethers.utils.parseEther("1000");
await deployer.sendTransaction({to: treasury.address, value: amount});
- // Lock OLAS balances with Voting Escrow
- const minWeightedBalance = await tokenomics.veOLASThreshold();
- await ve.setWeightedBalance(minWeightedBalance.toString());
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ const inflationPerYear = await tokenomics.getInflationForYear(0);
+ await ve.setWeightedBalance(inflationPerYear.toString());
await ve.createLock(deployer.address);
// Change the first service owner to the deployer (same for components and agents)
@@ -866,9 +980,9 @@ describe("DispenserDevIncentives", async () => {
const amount = ethers.utils.parseEther("1000");
await deployer.sendTransaction({to: treasury.address, value: amount});
- // Lock OLAS balances with Voting Escrow
- const minWeightedBalance = await tokenomics.veOLASThreshold();
- await ve.setWeightedBalance(minWeightedBalance.toString());
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ const inflationPerYear = await tokenomics.getInflationForYear(0);
+ await ve.setWeightedBalance(inflationPerYear.toString());
await ve.createLock(deployer.address);
// Change the first service owner to the deployer (same for components and agents)
@@ -965,9 +1079,9 @@ describe("DispenserDevIncentives", async () => {
const amount = ethers.utils.parseEther("1000");
await deployer.sendTransaction({to: treasury.address, value: amount});
- // Lock OLAS balances with Voting Escrow
- const minWeightedBalance = await tokenomics.veOLASThreshold();
- await ve.setWeightedBalance(minWeightedBalance.toString());
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ const inflationPerYear = await tokenomics.getInflationForYear(0);
+ await ve.setWeightedBalance(inflationPerYear.toString());
await ve.createLock(deployer.address);
// Change the first service owner to the deployer (same for components and agents)
@@ -1083,9 +1197,9 @@ describe("DispenserDevIncentives", async () => {
const amount = ethers.utils.parseEther("1000");
await deployer.sendTransaction({to: treasury.address, value: amount});
- // Lock OLAS balances with Voting Escrow
- const minWeightedBalance = await tokenomics.veOLASThreshold();
- await ve.setWeightedBalance(minWeightedBalance.toString());
+ // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation
+ const inflationPerYear = await tokenomics.getInflationForYear(0);
+ await ve.setWeightedBalance(inflationPerYear.toString());
await ve.createLock(deployer.address);
// Change the first service owner to the deployer (same for components and agents)
@@ -1165,7 +1279,12 @@ describe("DispenserDevIncentives", async () => {
const amount = ethers.utils.parseEther("1000");
await deployer.sendTransaction({to: treasury.address, value: amount});
- // Lock OLAS balances with Voting Escrow for the attacker
+ // Unset attack mode in order to receive initial funds
+ await attacker.setAttackMode(false);
+ await deployer.sendTransaction({to: attacker.address, value: amount});
+ await attacker.setAttackMode(true);
+
+ // Lock OLAS balances for attacker
await ve.createLock(attacker.address);
// Change the first service owner to the attacker (same for components and agents)
@@ -1174,7 +1293,7 @@ describe("DispenserDevIncentives", async () => {
await agentRegistry.changeUnitOwner(1, attacker.address);
// Send donations to services
- await treasury.connect(deployer).depositServiceDonationsETH([1, 2], [regDepositFromServices, regDepositFromServices],
+ await attacker.depositServiceDonationsETH([1, 2], [regDepositFromServices, regDepositFromServices],
{value: twoRegDepositFromServices});
// Move more than one epoch in time
await helpers.time.increase(epochLen + 10);
diff --git a/test/Tokenomics.js b/test/Tokenomics.js
index c95b6134..3f27433b 100644
--- a/test/Tokenomics.js
+++ b/test/Tokenomics.js
@@ -1020,7 +1020,7 @@ describe("Tokenomics", async () => {
await snapshot.restore();
});
- it("Get to the epoch before the end of the OLAS year and try to change maxBond or epochLen", async () => {
+ it("Get to two epochs before the end of the OLAS year and try to change epochLen", async () => {
// Take a snapshot of the current state of the blockchain
const snapshot = await helpers.takeSnapshot();
@@ -1030,7 +1030,7 @@ describe("Tokenomics", async () => {
const yearChangeTime = timeLaunch + oneYear;
// Get to the time of more than one epoch length before the year change (1.5 epoch length)
- let timeEpochBeforeYearChange = yearChangeTime - epochLen - epochLen / 2;
+ const timeEpochBeforeYearChange = yearChangeTime - epochLen - epochLen / 2;
await helpers.time.increaseTo(timeEpochBeforeYearChange);
await tokenomics.checkpoint();
@@ -1041,12 +1041,23 @@ describe("Tokenomics", async () => {
await helpers.time.increase(epochLen);
await tokenomics.checkpoint();
expect(await tokenomics.epochLen()).to.equal(2 * epochLen);
- // Restore the state of the blockchain back to the time half of the epoch before one epoch left for the current year
- snapshotInternal.restore();
+
+ // Restore to the state of the snapshot
+ await snapshot.restore();
+ });
+
+ it("Get to the epoch before the end of the OLAS year and try to change epochLen", async () => {
+ // Take a snapshot of the current state of the blockchain
+ const snapshot = await helpers.takeSnapshot();
+
+ // OLAS starting time
+ const timeLaunch = Number(await tokenomics.timeLaunch());
+ // One year time from the launch
+ const yearChangeTime = timeLaunch + oneYear;
// Get to the time of the half epoch length before the year change
// Meaning that the year does not change yet during the current epoch, but it will during the next one
- timeEpochBeforeYearChange += epochLen;
+ const timeEpochBeforeYearChange = yearChangeTime - epochLen / 2;
await helpers.time.increaseTo(timeEpochBeforeYearChange);
await tokenomics.checkpoint();