From 08ce169d493852274866fae05ac095187e77d212 Mon Sep 17 00:00:00 2001 From: antazoey Date: Tue, 10 Feb 2026 16:25:38 -0600 Subject: [PATCH 01/16] fix: update contracts manifest --- tplus/evm/manifests/tplus-contracts.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tplus/evm/manifests/tplus-contracts.json b/tplus/evm/manifests/tplus-contracts.json index e5f3380..c4f5324 100644 --- a/tplus/evm/manifests/tplus-contracts.json +++ b/tplus/evm/manifests/tplus-contracts.json @@ -1 +1 @@ -{"compilers":[{"contractTypes":["SigTest","MockTarget"],"name":"solidity","settings":{"optimizer":{"enabled":true,"runs":200},"outputSelection":{"src/.cache/solady/main/src/utils/ECDSA.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/solady/main/src/utils/EfficientHashLib.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/solady/main/src/utils/SafeTransferLib.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]}},"remappings":["solady=src/.cache/solady/main/src"],"viaIR":true},"version":"0.8.28+commit.7893614a"},{"contractTypes":["DepositVault","Registry","IAtomicSettlementCallback","Checkpointer"],"name":"solidity","settings":{"optimizer":{"enabled":true,"runs":200},"outputSelection":{"src/.cache/solady/main/src/utils/ECDSA.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/solady/main/src/utils/EfficientHashLib.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/solady/main/src/utils/SafeTransferLib.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/DepositVault.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/interfaces/IAtomicSettlementCallback.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]}},"remappings":["solady=src/.cache/solady/main/src"],"viaIR":true},"version":"0.8.30+commit.73712a01"}],"contractTypes":{"Checkpointer":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadySet","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotCouncilMultisig","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string[]","name":"approvedWithdrawals","type":"string[]"}],"name":"Withdrawals","type":"event"},{"inputs":[],"name":"CHECKPOINT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"sharedSignature","type":"bytes"},{"internalType":"bytes","name":"leaderSignature","type":"bytes"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint8[]","name":"stateRoot","type":"uint8[]"},{"internalType":"string[]","name":"approvedWithdrawals","type":"string[]"}],"internalType":"struct Checkpointer.Checkpoint","name":"_checkpoint","type":"tuple"}],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"councilMultisig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"leader","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"}],"name":"setDomainSeparator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCouncilMultisig","type":"address"}],"name":"setInitialCouncilMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newLeader","type":"address"}],"name":"setLeader","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCouncilMultisig","type":"address"}],"name":"setNewCouncilMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stateRoot","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stateRootNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"contractName":"Checkpointer","deploymentBytecode":{"bytecode":"0x608080604052346026575f80546001600160a01b03191633179055610b3e908161002b8239f35b5f80fdfe6080806040526004361015610012575f80fd5b5f3560e01c90816307ddaf53146108be575080633ea987d31461086657806340eedabb1461083e5780634331e8dd146107ea5780635fa993b214610792578063704b6c02146107455780637438b937146106f657806374ebc7a0146106d95780638bbb26a314610150578063cc2fc84514610105578063e1193e4c146100cb5763f851a440146100a0575f80fd5b346100c7575f3660031901126100c7575f546040516001600160a01b039091168152602090f35b5f80fd5b346100c7575f3660031901126100c75760206040517ff0231fa1a05c1ebcb4f35a12b1dcea172e840b8488bfdf9a22a26a8c427f94d88152f35b346100c75760203660031901126100c7576004356005548110156100c75760209060055f5260ff8160051c5f516020610ae95f395f51905f52015460f86040519360031b161c168152f35b346100c75760603660031901126100c75760043567ffffffffffffffff81116100c7576101819036906004016108e1565b60243567ffffffffffffffff81116100c7576101a19036906004016108e1565b906044359267ffffffffffffffff84116100c7578360040191606060031986360301126100c757823593600354918286036100c75760248701916101e5838761090f565b906040519060208201928391905f905b8082106106b45750505090610216816044949303601f198101835282610945565b519020980194610226868861090f565b610232819c929c610967565b9b6102406040519d8e610945565b818d5260208d019160051b8101903682116100c75780925b82841061067757505050508a51986102886102728b610967565b9a6102806040519c8d610945565b808c52610967565b60208b019b90601f1901368d375f5b8d518110156102c857808c8f826102b36001956102c1936109d3565b5160208151910120926109d3565b5201610297565b506040518b5160208201919082908f905f5b81811061066157505050918161030361039f97959361039999979503601f198101835282610945565b5190206040519160208301937ff0231fa1a05c1ebcb4f35a12b1dcea172e840b8488bfdf9a22a26a8c427f94d885526040840152606083015260808201526080815261035060a082610945565b5190206004549060405190602082019261190160f01b84526022830152604282015260428152610381606282610945565b51902093849160018060a01b035f541693369161097f565b916109fb565b15610652576103996103be9360018060a01b036001541693369161097f565b15610652575f19821461063e5760016103db92016003558361090f565b929067ffffffffffffffff841161062a5768010000000000000000841161062a57600554846005558085106105a0575b509260055f528060051c5f5b81811061055e5750601f1982169091039081610500575b505061043a925061090f565b906040519082602083016020845252604082019060408460051b84010193815f90601e19813603015b838310610492577fef889901cd5d865c829bdf171647f02f76efbce3c0cba77197094981f41a727c87890388a1005b909192939496603f198782030188528535828112156100c7578301906020823592019167ffffffffffffffff81116100c75780360383136100c7576020828280600196849695859652848401375f828201840152601f01601f19160101999190910196019493019190610463565b5f9485925b80871061052a57505061043a94505f516020610ae95f395f51905f520155838061042e565b909260206105536001928961053e886109c5565b919060ff809160031b9316831b921b19161790565b940196019590610505565b5f5f5b6020811061058357505f516020610ae95f395f51905f52820155600101610417565b969060206105976001928a61053e866109c5565b92019701610561565b601f80860160051c910160051c5f516020610ae95f395f51905f520190601f8616806105f0575b505f516020610ae95f395f51905f52015b8181106105e5575061040b565b5f81556001016105d8565b7f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3daf8201908154905f199060200360031b1c169055866105c7565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b638baa579f60e01b5f5260045ffd5b82518452602093840193909201916001016102da565b833567ffffffffffffffff81116100c757820136601f820112156100c7576020916106a983923690848135910161097f565b815201930192610258565b90919283359060ff82168092036100c7576020816001938293520194019201906101f5565b346100c7575f3660031901126100c7576020600354604051908152f35b346100c75760203660031901126100c7575f546001600160a01b031633036107365760045461072757600480359055005b63a741a04560e01b5f5260045ffd5b637bfa4b9f60e01b5f5260045ffd5b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7575f546001600160a01b03811633036107365781156100c7576001600160a01b031916175f55005b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7576002546001600160a01b03811633036107db576001600160a01b03191617600255005b638d62b6d960e01b5f5260045ffd5b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7576002546001600160a01b031633036107db576bffffffffffffffffffffffff60a01b60015416176001555f80f35b346100c7575f3660031901126100c7576001546040516001600160a01b039091168152602090f35b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7575f546001600160a01b03163303610736576002546001600160a01b038116610727576001600160a01b03191617600255005b346100c7575f3660031901126100c7576002546001600160a01b03168152602090f35b9181601f840112156100c75782359167ffffffffffffffff83116100c757602083818601950101116100c757565b903590601e19813603018212156100c7570180359067ffffffffffffffff82116100c757602001918160051b360383136100c757565b90601f8019910116810190811067ffffffffffffffff82111761062a57604052565b67ffffffffffffffff811161062a5760051b60200190565b92919267ffffffffffffffff821161062a57604051916109a9601f8201601f191660200184610945565b8294818452818301116100c7578281602093845f960137010152565b3560ff811681036100c75790565b80518210156109e75760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b90915f91906001600160a01b03821615610ae05760405192600484019460248501956044860192853b15610a6457509186939160209593630b135d3f60e11b8852526040845281518501809260045afa9360443d01915afa9151630b135d3f60e11b1491161690565b979650509050815180604014610abb57604114610a815750505050565b60209293955060608201515f1a835260408201516060525b5f5201516040526020600160805f825afa511860601b3d11915f606052604052565b506020929395506040820151601b8160ff1c01845260018060ff1b0316606052610a99565b505050505f9056fe036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0a2646970667358221220f09db22dfd6229ef82c2a681d2b8b25a406132cc8a7af0b418c1fe369f9f1f9964736f6c634300081e0033"},"devdoc":{"details":"Designed for use in DStack-like distributed settlement systems.","events":{"Withdrawals(string[])":{"params":{"approvedWithdrawals":"List of withdrawal IDs approved in the checkpoint."}}},"kind":"dev","methods":{"checkpoint(bytes,bytes,(uint256,uint8[],string[]))":{"details":"Requires valid EIP-712 signatures from both admin and leader.","params":{"_checkpoint":"The checkpoint payload to commit.","leaderSignature":"Signature by the leader.","sharedSignature":"Signature by the admin."}},"constructor":{"details":"Sets the deployer as the initial admin."},"setAdmin(address)":{"params":{"newAdmin":"The new admin address."}},"setDomainSeparator(bytes32)":{"params":{"domainSeparator":"The domain separator to store."}},"setInitialCouncilMultisig(address)":{"params":{"newCouncilMultisig":"The council's Gnosis Safe address."}},"setLeader(address)":{"details":"This should be reviewed depending on the leader rotation mechanism.","params":{"newLeader":"The address of the new leader node."}},"setNewCouncilMultisig(address)":{"params":{"newCouncilMultisig":"The new multisig address."}}},"stateVariables":{"admin":{"details":"Should be set to the DStack app shared secret public key."},"councilMultisig":{"details":"Can rotate the leader and self."},"leader":{"details":"Leader is responsible for signing and submitting new checkpoints."},"stateRoot":{"details":"Serialized as `(user, eth_balance, usdc_balance, deposit_nonce, is_mm)` tuples. In production, this may store multiple roots and rotate."},"stateRootNonce":{"details":"Used to prevent replay attacks and enforce checkpoint ordering."}},"title":"Checkpointer","version":1},"methodIdentifiers":{"CHECKPOINT_TYPEHASH()":"0xe1193e4c","admin()":"0xf851a440","checkpoint(bytes,bytes,(uint256,uint8[],string[]))":"0x8bbb26a3","councilMultisig()":"0x07ddaf53","leader()":"0x40eedabb","setAdmin(address)":"0x704b6c02","setDomainSeparator(bytes32)":"0x7438b937","setInitialCouncilMultisig(address)":"0x3ea987d3","setLeader(address)":"0x4331e8dd","setNewCouncilMultisig(address)":"0x5fa993b2","stateRoot(uint256)":"0xcc2fc845","stateRootNonce()":"0x74ebc7a0"},"runtimeBytecode":{"bytecode":"0x6080806040526004361015610012575f80fd5b5f3560e01c90816307ddaf53146108be575080633ea987d31461086657806340eedabb1461083e5780634331e8dd146107ea5780635fa993b214610792578063704b6c02146107455780637438b937146106f657806374ebc7a0146106d95780638bbb26a314610150578063cc2fc84514610105578063e1193e4c146100cb5763f851a440146100a0575f80fd5b346100c7575f3660031901126100c7575f546040516001600160a01b039091168152602090f35b5f80fd5b346100c7575f3660031901126100c75760206040517ff0231fa1a05c1ebcb4f35a12b1dcea172e840b8488bfdf9a22a26a8c427f94d88152f35b346100c75760203660031901126100c7576004356005548110156100c75760209060055f5260ff8160051c5f516020610ae95f395f51905f52015460f86040519360031b161c168152f35b346100c75760603660031901126100c75760043567ffffffffffffffff81116100c7576101819036906004016108e1565b60243567ffffffffffffffff81116100c7576101a19036906004016108e1565b906044359267ffffffffffffffff84116100c7578360040191606060031986360301126100c757823593600354918286036100c75760248701916101e5838761090f565b906040519060208201928391905f905b8082106106b45750505090610216816044949303601f198101835282610945565b519020980194610226868861090f565b610232819c929c610967565b9b6102406040519d8e610945565b818d5260208d019160051b8101903682116100c75780925b82841061067757505050508a51986102886102728b610967565b9a6102806040519c8d610945565b808c52610967565b60208b019b90601f1901368d375f5b8d518110156102c857808c8f826102b36001956102c1936109d3565b5160208151910120926109d3565b5201610297565b506040518b5160208201919082908f905f5b81811061066157505050918161030361039f97959361039999979503601f198101835282610945565b5190206040519160208301937ff0231fa1a05c1ebcb4f35a12b1dcea172e840b8488bfdf9a22a26a8c427f94d885526040840152606083015260808201526080815261035060a082610945565b5190206004549060405190602082019261190160f01b84526022830152604282015260428152610381606282610945565b51902093849160018060a01b035f541693369161097f565b916109fb565b15610652576103996103be9360018060a01b036001541693369161097f565b15610652575f19821461063e5760016103db92016003558361090f565b929067ffffffffffffffff841161062a5768010000000000000000841161062a57600554846005558085106105a0575b509260055f528060051c5f5b81811061055e5750601f1982169091039081610500575b505061043a925061090f565b906040519082602083016020845252604082019060408460051b84010193815f90601e19813603015b838310610492577fef889901cd5d865c829bdf171647f02f76efbce3c0cba77197094981f41a727c87890388a1005b909192939496603f198782030188528535828112156100c7578301906020823592019167ffffffffffffffff81116100c75780360383136100c7576020828280600196849695859652848401375f828201840152601f01601f19160101999190910196019493019190610463565b5f9485925b80871061052a57505061043a94505f516020610ae95f395f51905f520155838061042e565b909260206105536001928961053e886109c5565b919060ff809160031b9316831b921b19161790565b940196019590610505565b5f5f5b6020811061058357505f516020610ae95f395f51905f52820155600101610417565b969060206105976001928a61053e866109c5565b92019701610561565b601f80860160051c910160051c5f516020610ae95f395f51905f520190601f8616806105f0575b505f516020610ae95f395f51905f52015b8181106105e5575061040b565b5f81556001016105d8565b7f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3daf8201908154905f199060200360031b1c169055866105c7565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b638baa579f60e01b5f5260045ffd5b82518452602093840193909201916001016102da565b833567ffffffffffffffff81116100c757820136601f820112156100c7576020916106a983923690848135910161097f565b815201930192610258565b90919283359060ff82168092036100c7576020816001938293520194019201906101f5565b346100c7575f3660031901126100c7576020600354604051908152f35b346100c75760203660031901126100c7575f546001600160a01b031633036107365760045461072757600480359055005b63a741a04560e01b5f5260045ffd5b637bfa4b9f60e01b5f5260045ffd5b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7575f546001600160a01b03811633036107365781156100c7576001600160a01b031916175f55005b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7576002546001600160a01b03811633036107db576001600160a01b03191617600255005b638d62b6d960e01b5f5260045ffd5b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7576002546001600160a01b031633036107db576bffffffffffffffffffffffff60a01b60015416176001555f80f35b346100c7575f3660031901126100c7576001546040516001600160a01b039091168152602090f35b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7575f546001600160a01b03163303610736576002546001600160a01b038116610727576001600160a01b03191617600255005b346100c7575f3660031901126100c7576002546001600160a01b03168152602090f35b9181601f840112156100c75782359167ffffffffffffffff83116100c757602083818601950101116100c757565b903590601e19813603018212156100c7570180359067ffffffffffffffff82116100c757602001918160051b360383136100c757565b90601f8019910116810190811067ffffffffffffffff82111761062a57604052565b67ffffffffffffffff811161062a5760051b60200190565b92919267ffffffffffffffff821161062a57604051916109a9601f8201601f191660200184610945565b8294818452818301116100c7578281602093845f960137010152565b3560ff811681036100c75790565b80518210156109e75760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b90915f91906001600160a01b03821615610ae05760405192600484019460248501956044860192853b15610a6457509186939160209593630b135d3f60e11b8852526040845281518501809260045afa9360443d01915afa9151630b135d3f60e11b1491161690565b979650509050815180604014610abb57604114610a815750505050565b60209293955060608201515f1a835260408201516060525b5f5201516040526020600160805f825afa511860601b3d11915f606052604052565b506020929395506040820151601b8160ff1c01845260018060ff1b0316606052610a99565b505050505f9056fe036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0a2646970667358221220f09db22dfd6229ef82c2a681d2b8b25a406132cc8a7af0b418c1fe369f9f1f9964736f6c634300081e0033"},"sourceId":"src/Checkpointer.sol","sourcemap":"420:6397:4:-:0;;;;;;;2553:18;420:6397;;-1:-1:-1;;;;;;420:6397:4;2561:10;420:6397;;;;;;;;;;;;;","userdoc":{"errors":{"AlreadySet()":[{"notice":"Reverts if a value has already been set."}],"InvalidSignature()":[{"notice":"Reverts if a signature does not match the expected signer or payload."}],"NotAdmin()":[{"notice":"Reverts if caller is not the admin."}],"NotCouncilMultisig()":[{"notice":"Reverts if caller is not the current council multisig."}]},"events":{"Withdrawals(string[])":{"notice":"Emitted when a new list of approved withdrawals is recorded in a checkpoint."}},"kind":"user","methods":{"CHECKPOINT_TYPEHASH()":{"notice":"Typehash used for EIP-712 encoding of the Checkpoint struct."},"admin()":{"notice":"Address with the authority to set initial parameters."},"checkpoint(bytes,bytes,(uint256,uint8[],string[]))":{"notice":"Checkpoint submitted by a node to update the system state."},"constructor":{"notice":"Contract constructor."},"councilMultisig()":{"notice":"Gnosis Safe address used as the council multisig."},"leader()":{"notice":"Public key of the current designated leader node."},"setAdmin(address)":{"notice":"Transfers admin control to a new address."},"setDomainSeparator(bytes32)":{"notice":"Sets the EIP-712 domain separator used for verifying signatures."},"setInitialCouncilMultisig(address)":{"notice":"Sets the initial council multisig address."},"setLeader(address)":{"notice":"Sets the leader node address."},"setNewCouncilMultisig(address)":{"notice":"Allows the current council to rotate itself to a new address."},"stateRoot(uint256)":{"notice":"The current state root, encoded as a serialized vector."},"stateRootNonce()":{"notice":"Monotonically increasing nonce for checkpoint submissions."}},"notice":"Tracks and validates state root checkpoints using EIP-712 signatures from admin and leader nodes.","version":1}},"DepositVault":{"abi":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EmptyOrders","type":"error"},{"inputs":[],"name":"Expired","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"given","type":"uint256"}],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotExecutor","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"Settled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrew","type":"event"},{"inputs":[],"name":"ORDER_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"settler","type":"bytes32"},{"internalType":"address","name":"executor","type":"address"}],"name":"addSettlerExecutor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"approvedSettlers","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"canDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"depositCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct DepositVault.Settlement","name":"order","type":"tuple"},{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"executeAtomicSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getApprovedSettlers","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ownerWithdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pendingSettlements","outputs":[{"components":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct DepositVault.Settlement","name":"settlement","type":"tuple"},{"internalType":"address","name":"target","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct DepositVault.Settlement","name":"settlement","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct DepositVault.SignedSettlement[]","name":"orders","type":"tuple[]"},{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"validUntil","type":"uint256"}],"name":"pullBatchSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"user","type":"bytes32"}],"name":"pushBatchSettlements","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"settler","type":"bytes32"}],"name":"removeSettler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"authorized","type":"bool"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setDepositorStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"}],"name":"setDomainSeparator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"settlementCaps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"settlementCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct DepositVault.Withdrawal","name":"withdrawal","type":"tuple"},{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"withdrawalCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"contractName":"DepositVault","deploymentBytecode":{"bytecode":"0x60803460c457601f61171a38819003918201601f19168301916001600160401b0383118484101760c857808492604094855283398101031260c45780516001600160a01b038116919082900360c45760200151908015608f578060018060a01b03195f5416175f555f52600a60205260405f20600160ff1982541617905560015560405161163d90816100dd8239f35b60405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b21037bbb732b960991b6044820152606490fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610011575f80fd5b5f5f3560e01c806313af4035146112065780631a31cc4d146110a1578063224b93e11461105a57806324d7806c1461101d5780632fe7a79714610f8d5780633a87fe4d14610f555780633d63ea9314610f2b57806341774bfe14610ded5780634b0bddd214610da45780634bf0d33114610d675780637438b93714610d3657806382ff8b1e14610d0c5780638da5cb5b14610ce557806392698ac614610c2f57806398af977214610bf75780639a39f344146108c4578063a815476f1461089a578063ad9fa8bc14610761578063bf5b0e6f14610479578063c8c57ba6146102dd578063d954863c146101bc578063f585b64f146101545763f973a20914610117575f80fd5b3461015157806003193601126101515760206040517f3a0cb10b78ebd9ca317b25e5ca18c0e451c56fb5d187fc2f8745cb1b6834d3188152f35b80fd5b50346101515760603660031901126101515761016e611251565b610176611267565b82549091906001600160a01b031633036101ad576001600160a01b038216156101a9576101a69160443591611558565b80f35b8280fd5b6330cd747160e01b8352600483fd5b5034610151576060366003190112610151576004356101d9611267565b604435338452600b60205260ff604085205416156102ab578015610280577f9d677c46e10ba33882144473956fae8d2c52353dcde5aab8230d1bd280cfc3b48161022685933033876115a9565b8286526008602090815260408088205481516001600160a01b039790971687529186019290925293a381526008602052604081208054906001820180921161026c575580f35b634e487b7160e01b83526011600452602483fd5b606460405162461bcd60e51b81526020600482015260046024820152635a65726f60e01b6044820152fd5b60405162461bcd60e51b815260206004820152600a60248201526910b232b837b9b4ba37b960b11b6044820152606490fd5b503461015157602036600319011261015157600435338252600a60205260ff6040832054161561046a57815b8183526006602052604083205463ffffffff821610156104015763ffffffff90828452600660205261033e81604086206112ee565b506103876040519161034f8361131b565b61035881611375565b8084526005909101546001600160a01b03908116602085018190526040830151606090930151923092166115a9565b51608080820151825160208085015160408087015160609788015182516001600160a01b039687168152948501939093529390931692820192909252938401529185917f9969fe768a70bff6317c8dea6fafd06f63a1ce37fd7a2a227862aced26fa7dfa91a31663ffffffff811461026c57600101610309565b5081526006602052604081208054908281558161041c578280f35b8160060291600683040361026c57825260208220908101905b818110610440578280f35b80836006925583600182015583600282015583600382015583600482015583600582015501610435565b637bfa4b9f60e01b8252600482fd5b503461071457366003190161012081126107145760a0136107145760c43560a43560e43567ffffffffffffffff8111610714576104ba903690600401611291565b6101049391933567ffffffffffffffff8111610714576104de903690600401611291565b919094834211610752575f85815260026020908152604080832033845260010190915290205460ff161561074357845f52600760205260405f2054956084359680880361072c5750600154936105326113ea565b946024358097610540611400565b6064359889928d8d604051958695602087019861055d968a61144c565b03601f198101825261056f9082611353565b51902060405161190160f01b6020820190815260228201939093526042808201929092529081526105a1606282611353565b519020916105ae926114b1565b33846105b86113ea565b916105c292611558565b845f52600760205260405f208054906001820180921161071857556105e56113ea565b90333b156107145760845f92846040519586948593631f8eac2760e11b855260018060a01b0316600485015289602485015260606044850152816064850152848401378181018301859052601f01601f1916810103018183335af18015610709576106d1575b5090816106847f9969fe768a70bff6317c8dea6fafd06f63a1ce37fd7a2a227862aced26fa7dfa9361067b611400565b309033906115a9565b6106cb61068f6113ea565b91610698611400565b604080516001600160a01b0395861681526020810196909652931692840192909252606083019190915281906080820190565b0390a380f35b7f9969fe768a70bff6317c8dea6fafd06f63a1ce37fd7a2a227862aced26fa7dfa929195505f61070091611353565b5f94909161064b565b6040513d5f823e3d90fd5b5f80fd5b634e487b7160e01b5f52601160045260245ffd5b87906306427aeb60e01b5f5260045260245260445ffd5b6361968ebb60e11b5f5260045ffd5b630407b05b60e31b5f5260045ffd5b346107145760403660031901126107145760043561077d611267565b5f549091906001600160a01b0316330361088b57805f52600460205260ff60405f20541615610834575b805f52600260205260405f208054600160401b811015610820576107d0916001820181556113d5565b81549060031b9060018060a01b038516821b9160018060a01b03901b19161790555f526002602052600160405f20019060018060a01b03165f5260205260405f20600160ff198254161790555f80f35b634e487b7160e01b5f52604160045260245ffd5b600354600160401b8110156108205761086d6108578260018594016003556113bd565b819391549060031b91821b915f19901b19161790565b9055805f52600460205260405f20600160ff198254161790556107a7565b6330cd747160e01b5f5260045ffd5b34610714576020366003190112610714576004355f526007602052602060405f2054604051908152f35b346107145760803660031901126107145760043567ffffffffffffffff811161071457366023820112156107145780600401359067ffffffffffffffff8211610714576024810190602436918460051b01011161071457602435906044356001600160a01b0381168082036107145760643580421161075257845f52600660205260405f205461071457335f52600a60205260ff60405f20541615610be857845f52600760205260405f205490600154938715610bd9575f925b8884106109a15788885f52600760205260405f2080549182018092116107185755005b6109ac848a8961142a565b608081013591808303610bc257506109c381611416565b91808a8c8b896020870135809460408901996109de8b611416565b908d60608c0135998a9460405195869560208701986109fd968a61144c565b03601f1981018252610a0f9082611353565b5190208d60405180916020820193610a3d9185909160429261190160f01b8352600283015260228201520190565b03601f1981018252610a4f9082611353565b51902092610a5c9261142a565b60a081013590601e1981360301821215610714570180359067ffffffffffffffff821161071457602001813603811361071457610a98926114b1565b8b5f52600660205260405f209460405192610ab28461131b565b60a08636031261071457610ae260405192610acc84611337565b610ad58861127d565b845284602085015261127d565b60408301526060820152836080820152825260208201948986528054600160401b81101561082057610b19916001820181556112ee565b929092610baf5751805183546001600160a01b03199081166001600160a01b0392831617855560208301516001868101919091556040840151600287018054841691851691909117905560608401516003870155608093909301516004860155965160059094018054909716931692909217909455928392610ba691908690610ba190611416565b611558565b0193019261097e565b634e487b7160e01b5f525f60045260245ffd5b90506306427aeb60e01b5f5260045260245260445ffd5b63164bb4b560e11b5f5260045ffd5b637bfa4b9f60e01b5f5260045ffd5b34610714576020366003190112610714576001600160a01b03610c18611251565b165f526005602052602060405f2054604051908152f35b34610714575f366003190112610714576040518060206003549283815201809260035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b905f5b818110610ccf5750505081610c8d910382611353565b604051918291602083019060208452518091526040830191905f5b818110610cb6575050500390f35b8251845285945060209384019390920191600101610ca8565b8254845260209093019260019283019201610c77565b34610714575f366003190112610714575f546040516001600160a01b039091168152602090f35b34610714576020366003190112610714576004355f526009602052602060405f2054604051908152f35b34610714576020366003190112610714575f546001600160a01b0316330361088b5760015461071457600435600155005b34610714576020366003190112610714576001600160a01b03610d88611251565b165f52600b602052602060ff60405f2054166040519015158152f35b3461071457610db2366112bf565b5f546001600160a01b0316330361088b57610deb9160018060a01b03165f52600a60205260405f209060ff801983541691151516179055565b005b34610714576020366003190112610714575f54600435906001600160a01b0316330361088b576003545f5b818110610ea3575b50505f52600260205260405f205f60018201905b8254811015610e775780610e4a600192856113d5565b838060a01b0391549060031b1c16828060a01b03165f528260205260405f2060ff19815416905501610e34565b82545f84558381610e8457005b5f5260205f20908101905b818110610e9857005b5f8155600101610e8f565b82610ead826113bd565b90549060031b1c14610ec157600101610e18565b905f19810190811161071857610857610edc610ee9926113bd565b90549060031b1c926113bd565b90556003548015610f17575f1901610f00816113bd565b81545f19600392831b1b1916909155558180610e20565b634e487b7160e01b5f52603160045260245ffd5b34610714576020366003190112610714576004355f526008602052602060405f2054604051908152f35b346107145760203660031901126107145760043560035481101561071457610f7e6020916113bd565b90549060031b1c604051908152f35b34610714576040366003190112610714576024356004355f52600660205260405f2080548210156107145760c091610fc4916112ee565b50610fce81611375565b6005909101546040805183516001600160a01b039081168252602080860151908301528285015181169282019290925260608085015190820152608093840151938101939093521660a0820152f35b34610714576020366003190112610714576001600160a01b0361103e611251565b165f52600a602052602060ff60405f2054166040519015158152f35b3461071457611068366112bf565b5f546001600160a01b0316330361088b57610deb9160018060a01b03165f52600b60205260405f209060ff801983541691151516179055565b3461071457366003190160e0811261071457606013610714576064356084356001600160a01b03811681036107145760a4359060c43567ffffffffffffffff8111610714576110f4903690600401611291565b92909181421161075257845f52600960205260405f205493604435948086036111ef57507fc4f5735f1abe60807c07c06560e4a6d7eb655a37442b6a47e3ab1998c9611e2f928694926111a86111b093600154956111506113ea565b9660243597889660405191602083019384526bffffffffffffffffffffffff199060601b1660408301528760548301528b60748301528c609483015260b482015260b481526111a060d482611353565b5190206114b1565b610ba16113ea565b6111b86113ea565b604080516001600160a01b039290921682526020820192909252a35f52600960205260405f20805490600182018092116107185755005b85906306427aeb60e01b5f5260045260245260445ffd5b346107145760203660031901126107145761121f611251565b5f54906001600160a01b038216330361088b576001600160a01b0316908115610714576001600160a01b031916175f55005b600435906001600160a01b038216820361071457565b602435906001600160a01b038216820361071457565b35906001600160a01b038216820361071457565b9181601f840112156107145782359167ffffffffffffffff8311610714576020838186019501011161071457565b6040906003190112610714576004356001600160a01b0381168103610714579060243580151581036107145790565b8054821015611307575f52600660205f20910201905f90565b634e487b7160e01b5f52603260045260245ffd5b6040810190811067ffffffffffffffff82111761082057604052565b60a0810190811067ffffffffffffffff82111761082057604052565b90601f8019910116810190811067ffffffffffffffff82111761082057604052565b9060405161138281611337565b82546001600160a01b039081168252600184015460208301526002840154166040820152600383015460608201526004909201546080830152565b6003548110156113075760035f5260205f2001905f90565b8054821015611307575f5260205f2001905f90565b6004356001600160a01b03811681036107145790565b6044356001600160a01b03811681036107145790565b356001600160a01b03811681036107145790565b91908110156113075760051b8101359060be1981360301821215610714570190565b93909796959260e095926101008601997f3a0cb10b78ebd9ca317b25e5ca18c0e451c56fb5d187fc2f8745cb1b6834d318875260018060a01b03166020870152604086015260018060a01b03166060850152608084015260a083015260c08201520152565b604080515f94909391811461152d576041146114fb575050505b6001600160a01b03165f908152600a602052604090205460ff16156114ec57565b638baa579f60e01b5f5260045ffd5b604080929394508101355f1a60205281375b5f526020604060805f60015afa505f6060523d60601851906040526114cb565b5060208082013560ff81901c601b0190915290356040526001600160ff1b031660605290915061150d565b919060145260345263a9059cbb60601b5f5260205f6044601082855af1908160015f5114161561158b575b50505f603452565b3b153d17101561159c575f80611583565b6390b8ec185f526004601cfd5b916040519360605260405260601b602c526323b872dd60601b600c5260205f6064601c82855af1908160015f511416156115e9575b50505f606052604052565b3b153d1710156115fa575f806115de565b637939f4245f526004601cfdfea2646970667358221220ac5e64c72ba97ba608c814b6fc02a2a4fe4d99cef6678855dab68dc06343c1aa64736f6c634300081e0033"},"devdoc":{"kind":"dev","methods":{"addSettlerExecutor(bytes32,address)":{"details":"Reverts with `NotOwner`; Only the admin can set the settler executor.","params":{"executor":": The settler's assigned executor address.","settler":": The settler's tplus account key."}},"constructor":{"params":{"_owner":"The address to set as the owner."}},"deposit(bytes32,address,uint256)":{"details":"Reverts if the amount is 0.","params":{"amount":": The amount of the token to deposit.","tokenAddress":": The address of the token to deposit.","user":": The user whose account will be credited with the deposit."}},"executeAtomicSettlement((address,uint256,address,uint256,uint256),bytes32,uint256,bytes,bytes)":{"details":"Reverts with `Expired` if the block timestamp is greater than `validUntil`.Reverts with `NotExecutor`; Only the executor can settle.Reverts with `InvalidNonce` if the nonce has already been used.Reverts with `SignatureError` if the signer is not an admin.","params":{"data":": The data to execute as part of settlement callback.","order":": The settlement order.","signature":": The signature from the t+ clearing engine.","user":": The t+ user who is executing the settlement.","validUntil":": How long until the signature expires."}},"getApprovedSettlers()":{"returns":{"_0":"An array of addresses (as bytes32) that are currently approved settlers."}},"pullBatchSettlement(((address,uint256,address,uint256,uint256),bytes)[],bytes32,address,uint256)":{"details":"Reverts with `Expired` if the block timestamp is greater than `validUntil`.Reverts if a batch settlement has already started.Reverts with `NotAdmin`; Only an admin can execute the settlement.Reverts with `InvalidNonce` if the nonce has already been used.Reverts with `SignatureError` if the signer is not an admin.","params":{"orders":": The settlement orders.","target":": The target address to send the token to, pull tokens from, and execute callback on.","user":": The t+ user who is executing the settlement.","validUntil":": The timestamp when the settlement signature expires."}},"pushBatchSettlements(bytes32)":{"details":"Reverts with `NotAdmin`; Only an admin can execute the settlement.","params":{"user":": The t+ user who is executing the settlement."}},"removeSettler(bytes32)":{"details":"Reverts with `NotOwner`; Only the admin can remove a settler.","params":{"settler":": The settler's tplus account key."}},"setAdmin(address,bool)":{"details":"Reverts with `NotOwner` if called by an address other than the admin.","params":{"account":"The address to grant or revoke approval rights.","authorized":"Whether the account is authorized to approve settlements/withdrawals."}},"setDomainSeparator(bytes32)":{"details":"Reverts with `NotOwner`; Only the admin can set the domain separator.","params":{"domainSeparator":": The value to set."}},"setOwner(address)":{"details":"Reverts with `NotOwner`; Only the owner can set a new owner."},"withdraw((address,uint256,uint256),bytes32,address,uint256,bytes)":{"details":"Reverts with `Expired` if the block timestamp is greater than `validUntil`.Reverts with `InvalidNonce` if the nonce has already been used.Reverts with `SignatureError` if the signer is not an admin.","params":{"signature":": t+ clearing engine signature.","target":": The target address to send the token to.","user":": The user whose account will be debited by the withdrawal.","validUntil":": The timestamp when the withdrawal signature expires.","withdrawal":": The withdrawal token and amount."}}},"stateVariables":{"ORDER_TYPEHASH":{"details":"ORDER_TYPEHASH = keccak256(\"Order(address tokenOut,uint256 amountOut,address tokenIn,uint256 amountIn,bytes32 user,uint256 nonce,uint256 validUntil)\");"},"owner":{"details":"Should be set to the DStack container shared secret address."},"settlementCaps":{"details":"Currently unused \u2014 implementation pending design finalization."}},"version":1},"methodIdentifiers":{"ORDER_TYPEHASH()":"0xf973a209","addSettlerExecutor(bytes32,address)":"0xad9fa8bc","approvedSettlers(uint256)":"0x3a87fe4d","canDeposit(address)":"0x4bf0d331","deposit(bytes32,address,uint256)":"0xd954863c","depositCounts(bytes32)":"0x3d63ea93","executeAtomicSettlement((address,uint256,address,uint256,uint256),bytes32,uint256,bytes,bytes)":"0xbf5b0e6f","getApprovedSettlers()":"0x92698ac6","isAdmin(address)":"0x24d7806c","owner()":"0x8da5cb5b","ownerWithdrawToken(address,address,uint256)":"0xf585b64f","pendingSettlements(bytes32,uint256)":"0x2fe7a797","pullBatchSettlement(((address,uint256,address,uint256,uint256),bytes)[],bytes32,address,uint256)":"0x9a39f344","pushBatchSettlements(bytes32)":"0xc8c57ba6","removeSettler(bytes32)":"0x41774bfe","setAdmin(address,bool)":"0x4b0bddd2","setDepositorStatus(address,bool)":"0x224b93e1","setDomainSeparator(bytes32)":"0x7438b937","setOwner(address)":"0x13af4035","settlementCaps(address)":"0x98af9772","settlementCounts(bytes32)":"0xa815476f","withdraw((address,uint256,uint256),bytes32,address,uint256,bytes)":"0x1a31cc4d","withdrawalCounts(bytes32)":"0x82ff8b1e"},"runtimeBytecode":{"bytecode":"0x60806040526004361015610011575f80fd5b5f5f3560e01c806313af4035146112065780631a31cc4d146110a1578063224b93e11461105a57806324d7806c1461101d5780632fe7a79714610f8d5780633a87fe4d14610f555780633d63ea9314610f2b57806341774bfe14610ded5780634b0bddd214610da45780634bf0d33114610d675780637438b93714610d3657806382ff8b1e14610d0c5780638da5cb5b14610ce557806392698ac614610c2f57806398af977214610bf75780639a39f344146108c4578063a815476f1461089a578063ad9fa8bc14610761578063bf5b0e6f14610479578063c8c57ba6146102dd578063d954863c146101bc578063f585b64f146101545763f973a20914610117575f80fd5b3461015157806003193601126101515760206040517f3a0cb10b78ebd9ca317b25e5ca18c0e451c56fb5d187fc2f8745cb1b6834d3188152f35b80fd5b50346101515760603660031901126101515761016e611251565b610176611267565b82549091906001600160a01b031633036101ad576001600160a01b038216156101a9576101a69160443591611558565b80f35b8280fd5b6330cd747160e01b8352600483fd5b5034610151576060366003190112610151576004356101d9611267565b604435338452600b60205260ff604085205416156102ab578015610280577f9d677c46e10ba33882144473956fae8d2c52353dcde5aab8230d1bd280cfc3b48161022685933033876115a9565b8286526008602090815260408088205481516001600160a01b039790971687529186019290925293a381526008602052604081208054906001820180921161026c575580f35b634e487b7160e01b83526011600452602483fd5b606460405162461bcd60e51b81526020600482015260046024820152635a65726f60e01b6044820152fd5b60405162461bcd60e51b815260206004820152600a60248201526910b232b837b9b4ba37b960b11b6044820152606490fd5b503461015157602036600319011261015157600435338252600a60205260ff6040832054161561046a57815b8183526006602052604083205463ffffffff821610156104015763ffffffff90828452600660205261033e81604086206112ee565b506103876040519161034f8361131b565b61035881611375565b8084526005909101546001600160a01b03908116602085018190526040830151606090930151923092166115a9565b51608080820151825160208085015160408087015160609788015182516001600160a01b039687168152948501939093529390931692820192909252938401529185917f9969fe768a70bff6317c8dea6fafd06f63a1ce37fd7a2a227862aced26fa7dfa91a31663ffffffff811461026c57600101610309565b5081526006602052604081208054908281558161041c578280f35b8160060291600683040361026c57825260208220908101905b818110610440578280f35b80836006925583600182015583600282015583600382015583600482015583600582015501610435565b637bfa4b9f60e01b8252600482fd5b503461071457366003190161012081126107145760a0136107145760c43560a43560e43567ffffffffffffffff8111610714576104ba903690600401611291565b6101049391933567ffffffffffffffff8111610714576104de903690600401611291565b919094834211610752575f85815260026020908152604080832033845260010190915290205460ff161561074357845f52600760205260405f2054956084359680880361072c5750600154936105326113ea565b946024358097610540611400565b6064359889928d8d604051958695602087019861055d968a61144c565b03601f198101825261056f9082611353565b51902060405161190160f01b6020820190815260228201939093526042808201929092529081526105a1606282611353565b519020916105ae926114b1565b33846105b86113ea565b916105c292611558565b845f52600760205260405f208054906001820180921161071857556105e56113ea565b90333b156107145760845f92846040519586948593631f8eac2760e11b855260018060a01b0316600485015289602485015260606044850152816064850152848401378181018301859052601f01601f1916810103018183335af18015610709576106d1575b5090816106847f9969fe768a70bff6317c8dea6fafd06f63a1ce37fd7a2a227862aced26fa7dfa9361067b611400565b309033906115a9565b6106cb61068f6113ea565b91610698611400565b604080516001600160a01b0395861681526020810196909652931692840192909252606083019190915281906080820190565b0390a380f35b7f9969fe768a70bff6317c8dea6fafd06f63a1ce37fd7a2a227862aced26fa7dfa929195505f61070091611353565b5f94909161064b565b6040513d5f823e3d90fd5b5f80fd5b634e487b7160e01b5f52601160045260245ffd5b87906306427aeb60e01b5f5260045260245260445ffd5b6361968ebb60e11b5f5260045ffd5b630407b05b60e31b5f5260045ffd5b346107145760403660031901126107145760043561077d611267565b5f549091906001600160a01b0316330361088b57805f52600460205260ff60405f20541615610834575b805f52600260205260405f208054600160401b811015610820576107d0916001820181556113d5565b81549060031b9060018060a01b038516821b9160018060a01b03901b19161790555f526002602052600160405f20019060018060a01b03165f5260205260405f20600160ff198254161790555f80f35b634e487b7160e01b5f52604160045260245ffd5b600354600160401b8110156108205761086d6108578260018594016003556113bd565b819391549060031b91821b915f19901b19161790565b9055805f52600460205260405f20600160ff198254161790556107a7565b6330cd747160e01b5f5260045ffd5b34610714576020366003190112610714576004355f526007602052602060405f2054604051908152f35b346107145760803660031901126107145760043567ffffffffffffffff811161071457366023820112156107145780600401359067ffffffffffffffff8211610714576024810190602436918460051b01011161071457602435906044356001600160a01b0381168082036107145760643580421161075257845f52600660205260405f205461071457335f52600a60205260ff60405f20541615610be857845f52600760205260405f205490600154938715610bd9575f925b8884106109a15788885f52600760205260405f2080549182018092116107185755005b6109ac848a8961142a565b608081013591808303610bc257506109c381611416565b91808a8c8b896020870135809460408901996109de8b611416565b908d60608c0135998a9460405195869560208701986109fd968a61144c565b03601f1981018252610a0f9082611353565b5190208d60405180916020820193610a3d9185909160429261190160f01b8352600283015260228201520190565b03601f1981018252610a4f9082611353565b51902092610a5c9261142a565b60a081013590601e1981360301821215610714570180359067ffffffffffffffff821161071457602001813603811361071457610a98926114b1565b8b5f52600660205260405f209460405192610ab28461131b565b60a08636031261071457610ae260405192610acc84611337565b610ad58861127d565b845284602085015261127d565b60408301526060820152836080820152825260208201948986528054600160401b81101561082057610b19916001820181556112ee565b929092610baf5751805183546001600160a01b03199081166001600160a01b0392831617855560208301516001868101919091556040840151600287018054841691851691909117905560608401516003870155608093909301516004860155965160059094018054909716931692909217909455928392610ba691908690610ba190611416565b611558565b0193019261097e565b634e487b7160e01b5f525f60045260245ffd5b90506306427aeb60e01b5f5260045260245260445ffd5b63164bb4b560e11b5f5260045ffd5b637bfa4b9f60e01b5f5260045ffd5b34610714576020366003190112610714576001600160a01b03610c18611251565b165f526005602052602060405f2054604051908152f35b34610714575f366003190112610714576040518060206003549283815201809260035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b905f5b818110610ccf5750505081610c8d910382611353565b604051918291602083019060208452518091526040830191905f5b818110610cb6575050500390f35b8251845285945060209384019390920191600101610ca8565b8254845260209093019260019283019201610c77565b34610714575f366003190112610714575f546040516001600160a01b039091168152602090f35b34610714576020366003190112610714576004355f526009602052602060405f2054604051908152f35b34610714576020366003190112610714575f546001600160a01b0316330361088b5760015461071457600435600155005b34610714576020366003190112610714576001600160a01b03610d88611251565b165f52600b602052602060ff60405f2054166040519015158152f35b3461071457610db2366112bf565b5f546001600160a01b0316330361088b57610deb9160018060a01b03165f52600a60205260405f209060ff801983541691151516179055565b005b34610714576020366003190112610714575f54600435906001600160a01b0316330361088b576003545f5b818110610ea3575b50505f52600260205260405f205f60018201905b8254811015610e775780610e4a600192856113d5565b838060a01b0391549060031b1c16828060a01b03165f528260205260405f2060ff19815416905501610e34565b82545f84558381610e8457005b5f5260205f20908101905b818110610e9857005b5f8155600101610e8f565b82610ead826113bd565b90549060031b1c14610ec157600101610e18565b905f19810190811161071857610857610edc610ee9926113bd565b90549060031b1c926113bd565b90556003548015610f17575f1901610f00816113bd565b81545f19600392831b1b1916909155558180610e20565b634e487b7160e01b5f52603160045260245ffd5b34610714576020366003190112610714576004355f526008602052602060405f2054604051908152f35b346107145760203660031901126107145760043560035481101561071457610f7e6020916113bd565b90549060031b1c604051908152f35b34610714576040366003190112610714576024356004355f52600660205260405f2080548210156107145760c091610fc4916112ee565b50610fce81611375565b6005909101546040805183516001600160a01b039081168252602080860151908301528285015181169282019290925260608085015190820152608093840151938101939093521660a0820152f35b34610714576020366003190112610714576001600160a01b0361103e611251565b165f52600a602052602060ff60405f2054166040519015158152f35b3461071457611068366112bf565b5f546001600160a01b0316330361088b57610deb9160018060a01b03165f52600b60205260405f209060ff801983541691151516179055565b3461071457366003190160e0811261071457606013610714576064356084356001600160a01b03811681036107145760a4359060c43567ffffffffffffffff8111610714576110f4903690600401611291565b92909181421161075257845f52600960205260405f205493604435948086036111ef57507fc4f5735f1abe60807c07c06560e4a6d7eb655a37442b6a47e3ab1998c9611e2f928694926111a86111b093600154956111506113ea565b9660243597889660405191602083019384526bffffffffffffffffffffffff199060601b1660408301528760548301528b60748301528c609483015260b482015260b481526111a060d482611353565b5190206114b1565b610ba16113ea565b6111b86113ea565b604080516001600160a01b039290921682526020820192909252a35f52600960205260405f20805490600182018092116107185755005b85906306427aeb60e01b5f5260045260245260445ffd5b346107145760203660031901126107145761121f611251565b5f54906001600160a01b038216330361088b576001600160a01b0316908115610714576001600160a01b031916175f55005b600435906001600160a01b038216820361071457565b602435906001600160a01b038216820361071457565b35906001600160a01b038216820361071457565b9181601f840112156107145782359167ffffffffffffffff8311610714576020838186019501011161071457565b6040906003190112610714576004356001600160a01b0381168103610714579060243580151581036107145790565b8054821015611307575f52600660205f20910201905f90565b634e487b7160e01b5f52603260045260245ffd5b6040810190811067ffffffffffffffff82111761082057604052565b60a0810190811067ffffffffffffffff82111761082057604052565b90601f8019910116810190811067ffffffffffffffff82111761082057604052565b9060405161138281611337565b82546001600160a01b039081168252600184015460208301526002840154166040820152600383015460608201526004909201546080830152565b6003548110156113075760035f5260205f2001905f90565b8054821015611307575f5260205f2001905f90565b6004356001600160a01b03811681036107145790565b6044356001600160a01b03811681036107145790565b356001600160a01b03811681036107145790565b91908110156113075760051b8101359060be1981360301821215610714570190565b93909796959260e095926101008601997f3a0cb10b78ebd9ca317b25e5ca18c0e451c56fb5d187fc2f8745cb1b6834d318875260018060a01b03166020870152604086015260018060a01b03166060850152608084015260a083015260c08201520152565b604080515f94909391811461152d576041146114fb575050505b6001600160a01b03165f908152600a602052604090205460ff16156114ec57565b638baa579f60e01b5f5260045ffd5b604080929394508101355f1a60205281375b5f526020604060805f60015afa505f6060523d60601851906040526114cb565b5060208082013560ff81901c601b0190915290356040526001600160ff1b031660605290915061150d565b919060145260345263a9059cbb60601b5f5260205f6044601082855af1908160015f5114161561158b575b50505f603452565b3b153d17101561159c575f80611583565b6390b8ec185f526004601cfd5b916040519360605260405260601b602c526323b872dd60601b600c5260205f6064601c82855af1908160015f511416156115e9575b50505f606052604052565b3b153d1710156115fa575f806115de565b637939f4245f526004601cfdfea2646970667358221220ac5e64c72ba97ba608c814b6fc02a2a4fe4d99cef6678855dab68dc06343c1aa64736f6c634300081e0033"},"sourceId":"src/DepositVault.sol","sourcemap":"332:17283:3:-:0;;;;;;;;;;;;;-1:-1:-1;;332:17283:3;;;;-1:-1:-1;;;;;332:17283:3;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;332:17283:3;;;;;;;;;;;;4877:20;;;332:17283;;;;;;;;;-1:-1:-1;332:17283:3;;;-1:-1:-1;332:17283:3;-1:-1:-1;332:17283:3;4949:7;332:17283;;;-1:-1:-1;332:17283:3;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;332:17283:3;;;;;;;;;;;;-1:-1:-1;;;332:17283:3;;;;;;;;-1:-1:-1;332:17283:3;;;;;;-1:-1:-1;332:17283:3;;;;;-1:-1:-1;332:17283:3","userdoc":{"errors":{"EmptyOrders()":[{"notice":"Reverts if an order array is empty."}],"Expired()":[{"notice":"Reverts if a signed operation is past its deadline."}],"InvalidNonce(uint256,uint256)":[{"notice":"Reverts if the nonce used in a transaction is incorrect."}],"InvalidSignature()":[{"notice":"Reverts if the signature provided is invalid."}],"NotAdmin()":[{"notice":"Reverts if the caller is not an admin."}],"NotExecutor()":[{"notice":"Reverts if the caller is not the authorized executor."}],"NotOwner()":[{"notice":"Reverts if the caller is not the owner."}]},"events":{"Deposited(bytes32,uint256,address,uint256)":{"notice":"Signals a deposit."},"Settled(bytes32,uint256,address,uint256,address,uint256)":{"notice":"Signals a settlement."},"Withdrew(bytes32,uint256,address,uint256)":{"notice":"Signals a withdrawal."}},"kind":"user","methods":{"ORDER_TYPEHASH()":{"notice":"EIP-712 typehash for an Order struct used in off-chain signature verification."},"addSettlerExecutor(bytes32,address)":{"notice":"Sets the settle executor."},"approvedSettlers(uint256)":{"notice":"List of all approved settler IDs."},"constructor":{"notice":"Initializes the contract and sets the owner. Also permits the owner to authorize settlements and withdrawals."},"deposit(bytes32,address,uint256)":{"notice":"Deposits a token into the vault."},"depositCounts(bytes32)":{"notice":"Maps settler IDs to their deposit count (nonce)."},"executeAtomicSettlement((address,uint256,address,uint256,uint256),bytes32,uint256,bytes,bytes)":{"notice":"Executes an atomic settlement."},"getApprovedSettlers()":{"notice":"Get the array of approved settlers."},"isAdmin(address)":{"notice":"True for any valid authority; used in settlement/withdrawal signature verification."},"owner()":{"notice":"The admin approves settlements and withdrawals."},"pendingSettlements(bytes32,uint256)":{"notice":"Maps settler IDs to their queue of pending batch settlements."},"pullBatchSettlement(((address,uint256,address,uint256,uint256),bytes)[],bytes32,address,uint256)":{"notice":"Pulls funds for execution during a settlement batch."},"pushBatchSettlements(bytes32)":{"notice":"Pushes expected funds from a batch settlement to the deposit vault."},"removeSettler(bytes32)":{"notice":"Removes a settler."},"setAdmin(address,bool)":{"notice":"Grants or revokes settlement and withdrawal approval rights to an address."},"setDomainSeparator(bytes32)":{"notice":"Sets the domain separators for EIP-712 signatures."},"setOwner(address)":{"notice":"Sets the owner of the vault."},"settlementCaps(address)":{"notice":"Maximum total tokens that can be settled in a single block for each token."},"settlementCounts(bytes32)":{"notice":"Maps settler IDs to their settlement count (nonce)."},"withdraw((address,uint256,uint256),bytes32,address,uint256,bytes)":{"notice":"Withdraws a token from the vault."},"withdrawalCounts(bytes32)":{"notice":"Maps settler IDs to their withdrawal count (nonce)."}},"version":1}},"IAtomicSettlementCallback":{"abi":[{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onAtomicSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"}],"contractName":"IAtomicSettlementCallback","deploymentBytecode":{"bytecode":"0x"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"onAtomicSettlement(address,uint256,bytes)":"0x3f1d584e"},"runtimeBytecode":{"bytecode":"0x"},"sourceId":"src/interfaces/IAtomicSettlementCallback.sol","sourcemap":"","userdoc":{"kind":"user","methods":{},"version":1}},"MockTarget":{"abi":[{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onAtomicSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"}],"contractName":"MockTarget","deploymentBytecode":{"bytecode":"0x6080806040523460135760b1908160188239f35b5f80fdfe6004361015600b575f80fd5b5f3560e01c633f1d584e14601d575f80fd5b3460775760603660031901126077576004356001600160a01b0381160360775760443567ffffffffffffffff811160775736602382011215607757806004013567ffffffffffffffff811160775736910160240111607757005b5f80fdfea26469706673582212206cf91bafe3a0f54d58f9735d82a4757234fa3d217135826792ecef05e5d5837c64736f6c634300081c0033"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"onAtomicSettlement(address,uint256,bytes)":"0x3f1d584e"},"runtimeBytecode":{"bytecode":"0x6004361015600b575f80fd5b5f3560e01c633f1d584e14601d575f80fd5b3460775760603660031901126077576004356001600160a01b0381160360775760443567ffffffffffffffff811160775736602382011215607757806004013567ffffffffffffffff811160775736910160240111607757005b5f80fdfea26469706673582212206cf91bafe3a0f54d58f9735d82a4757234fa3d217135826792ecef05e5d5837c64736f6c634300081c0033"},"sourceId":"src/MockTarget.sol","sourcemap":"149:148:4:-:0;;;;;;;;;;;;;;;;;","userdoc":{"kind":"user","methods":{},"version":1}},"Registry":{"abi":[{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotRiskManager","type":"error"},{"inputs":[{"internalType":"uint256","name":"chain","type":"uint256"},{"internalType":"bytes32","name":"addr","type":"bytes32"}],"name":"addVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"councilMultisig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint16","name":"index","type":"uint16"}],"name":"getAssetData","outputs":[{"components":[{"internalType":"bytes32","name":"assetAddress","type":"bytes32"},{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint256","name":"maxDeposits","type":"uint256"}],"internalType":"struct Registry.AssetData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"bytes32","name":"assetAddress","type":"bytes32"}],"name":"getAssetIndex","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"start","type":"uint16"},{"internalType":"uint16","name":"end","type":"uint16"}],"name":"getAssets","outputs":[{"components":[{"internalType":"bytes32","name":"assetAddress","type":"bytes32"},{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint256","name":"maxDeposits","type":"uint256"}],"internalType":"struct Registry.AssetData[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"start","type":"uint16"},{"internalType":"uint16","name":"end","type":"uint16"}],"name":"getRiskParameters","outputs":[{"components":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxLiabilities","type":"uint256"}],"internalType":"struct Registry.RiskParameters[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"start","type":"uint16"},{"internalType":"uint16","name":"end","type":"uint16"}],"name":"getVaults","outputs":[{"components":[{"internalType":"uint256","name":"chain","type":"uint256"},{"internalType":"bytes32","name":"vaultAddress","type":"bytes32"}],"internalType":"struct Registry.Vault[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"idx","type":"uint256"}],"name":"removeVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"riskManagerMultisig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"riskParameters","outputs":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxLiabilities","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"index","type":"uint16"},{"components":[{"internalType":"bytes32","name":"assetAddress","type":"bytes32"},{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint256","name":"maxDeposits","type":"uint256"}],"internalType":"struct Registry.AssetData","name":"data","type":"tuple"}],"name":"setAssetData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"multisig","type":"address"}],"name":"setCouncilMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"multisig","type":"address"}],"name":"setRiskManagerMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"index","type":"uint16"},{"components":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxLiabilities","type":"uint256"}],"internalType":"struct Registry.RiskParameters","name":"parameters","type":"tuple"}],"name":"setRiskParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vaults","outputs":[{"internalType":"uint256","name":"chain","type":"uint256"},{"internalType":"bytes32","name":"vaultAddress","type":"bytes32"}],"stateMutability":"view","type":"function"}],"contractName":"Registry","deploymentBytecode":{"bytecode":"0x608034606f57601f61112a38819003918201601f19168301916001600160401b03831184841017607357808492602094604052833981010312606f57516001600160a01b03811690819003606f575f80546001600160a01b0319169190911790556040516110a290816100888239f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f3560e01c90816307ddaf5314610947575080630cb661c7146108b1578063114bb9c51461085957806339006126146108245780633e112053146107d15780634ffcbdfb1461077e578063525ea8b714610756578063704b6c02146107095780638c64ea4a146106cc5780639fd7285c14610652578063b686043814610569578063c9c86796146103f3578063ca4ec14b14610372578063eaadd9761461023a578063f0fef575146101a5578063f247ceb9146101025763f851a440146100d7575f80fd5b346100fe575f3660031901126100fe575f546040516001600160a01b039091168152602090f35b5f80fd5b346100fe5760403660031901126100fe5761011b61098c565b61ffff61012661097b565b61012e610a7e565b50165f5260066020526001600160401b0360405f2091165f52602052606060405f20600261015a6109f1565b91805483526001600160401b036001820154166020840152015460408201526101a3604051809260408091805184526001600160401b0360208201511660208501520151910152565bf35b346100fe5760403660031901126100fe576101cf6101c161096a565b6101c961097b565b90610f3a565b6040518091602082016020835281518091526020604084019201905f5b8181106101fa575050500390f35b91935091602060806001926060875160ff815116835260ff85820151168584015260408101516040840152015160608201520194019101918493926101ec565b346100fe5760203660031901126100fe575f54600435906001600160a01b03163303610363576004549081811015610330575f1982019182119190825b6102df57818110156102f357600181018082116102df57610297906109a2565b50906102a2816109a2565b6102cc578260019382036102ba575b50500182610277565b805482558301549083015584806102b1565b634e487b7160e01b5f525f60045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b600454801561031c575f1901610308816109a2565b6102cc5760015f9182815501556004555f80f35b634e487b7160e01b5f52603160045260245ffd5b60405162461bcd60e51b815260206004820152600b60248201526a6f75746f66626f756e647360a81b6044820152606490fd5b637bfa4b9f60e01b5f5260045ffd5b346100fe5760403660031901126100fe575f546001600160a01b031633036103635761039c610a10565b600435815260208101906024358252600454600160401b8110156103df578060016103ca92016004556109a2565b9290926102cc57600191518355519101555f80f35b634e487b7160e01b5f52604160045260245ffd5b346100fe5760803660031901126100fe5761040c61096a565b60603660231901126100fe576104206109f1565b6024358152604435916001600160401b03831683036100fe5760208201928352606435604083019081526001549091906001600160a01b0316330361055b5761ffff1691825f526006602052600160405f2001541590835f52600660205260405f206001600160401b0380875116165f52602052600260405f20541593855f52600660205260405f206001600160401b0380895116165f5260205260405f2092518355600183016001600160401b038851166001600160401b031982541617905551910155610545575b6104f057005b5f5260066020526001600160401b03600160405f2001915116908054600160401b8110156103df5761052791600182018155610af2565b6001600160401b03829392549160031b92831b921b19161790555f80f35b600554600181018091116102df576005556104ea565b6206732360e51b5f5260045ffd5b346100fe5760a03660031901126100fe5761058261096a565b60803660231901126100fe576105966109d2565b9060243560ff811681036100fe57825260443560ff811681036100fe57602083019081526040830160643581526060840191608435835260018060a01b0360015416330361055b5761ffff600554941693841015610624576002935f52600360205260ff60405f2095511661ff008654925160081b169161ffff191617178455516001840155519101555f80f35b60405162461bcd60e51b815260206004820152600660248201526508585cdcd95d60d21b6044820152606490fd5b346100fe5760403660031901126100fe5761067c61066e61096a565b61067661097b565b90610ded565b6040518091602082016020835281518091526020604084019201905f5b8181106106a7575050500390f35b8251805185526020908101518186015286955060409094019390920191600101610699565b346100fe5760203660031901126100fe576004356004548110156100fe576106f56040916109a2565b506001815491015482519182526020820152f35b346100fe5760203660031901126100fe576004356001600160a01b038116908190036100fe575f546001600160a01b03811633036103635781156100fe576001600160a01b031916175f55005b346100fe575f3660031901126100fe576001546040516001600160a01b039091168152602090f35b346100fe5760203660031901126100fe576004356001600160a01b038116908190036100fe575f546001600160a01b03163303610363576bffffffffffffffffffffffff60a01b60015416176001555f80f35b346100fe5760203660031901126100fe576004356001600160a01b038116908190036100fe575f546001600160a01b03163303610363576bffffffffffffffffffffffff60a01b60025416176002555f80f35b346100fe5760403660031901126100fe57602061084b61084261098c565b60243590610d3b565b63ffffffff60405191168152f35b346100fe5760203660031901126100fe5761ffff61087561096a565b165f526003602052608060405f20805490600260018201549101549060ff60405193818116855260081c16602084015260408301526060820152f35b346100fe5760403660031901126100fe576108db6108cd61096a565b6108d561097b565b90610b27565b6040518091602082016020835281518091526020604084019201905f5b818110610906575050500390f35b919350916020606082610939600194885160408091805184526001600160401b0360208201511660208501520151910152565b0194019101918493926108f8565b346100fe575f3660031901126100fe576002546001600160a01b03168152602090f35b6004359061ffff821682036100fe57565b6024359061ffff821682036100fe57565b600435906001600160401b03821682036100fe57565b6004548110156109be5760045f5260205f209060011b01905f90565b634e487b7160e01b5f52603260045260245ffd5b60405190608082018281106001600160401b038211176103df57604052565b60405190606082018281106001600160401b038211176103df57604052565b60405190604082018281106001600160401b038211176103df57604052565b6040519190601f01601f191682016001600160401b038111838210176103df57604052565b61ffff1661ffff81146102df5760010190565b6001600160401b0381116103df5760051b60200190565b610a866109f1565b905f82525f60208301525f6040830152565b610aa26020610a2f565b5f815290815f90815b828110610ab757505050565b602090610ac2610a7e565b82828501015201610aab565b9061ffff8091169116039061ffff82116102df57565b5f1981146102df5760010190565b91909180548310156109be575f52601860205f208360021c019260031b1690565b80518210156109be5760209160051b010190565b6005545f939290845b61ffff861682811015610b65575f526006602052600160405f20015481018091116102df57610b5f9095610a54565b94610b30565b5094509192909261ffff81169480861015610d1e578061ffff861611610d2f575b5061ffff841693858510610d1e5761ffff91610ba491969396610ace565b1692610bb7610bb285610a67565b610a2f565b84815290601f19610bc786610a67565b015f5b818110610d0157505f93905083805b61ffff82169680881080610cf8575b15610cec575f915b885f526006602052600160405f200154831080610ce3575b15610ccd578481101580610cc4575b610c34575b610c28610c2e91610ae4565b92610ae4565b91610bf0565b5f8981526006602052604090209097610c2e91610c2891610cbb916001600160401b0380610c658960018501610af2565b90549060031b1c16165f5260205260405f206002610c816109f1565b91805483526001600160401b03600182015416602084015201546040820152610caa828c610b13565b52610cb5818b610b13565b50610ae4565b98915050610c1c565b50858110610c17565b9992909750610cdc9150610a54565b9097610bd9565b50898810610c08565b50505050509250505090565b50888710610be8565b602090610d0f989598610a7e565b82828701015201969396610bca565b505092505050610d2c610a98565b90565b61ffff1693505f610b86565b60055490915f5b61ffff811683811015610d8c57805f52600660205260405f206001600160401b0386165f5260205260405f20548314610d845750610d7f90610a54565b610d42565b935050505090565b505050505063ffffffff90565b610da36020610a2f565b5f815290815f90815b828110610db857505050565b602090610dc3610a10565b5f81525f8382015282828501015201610dac565b9061ffff8091169116019061ffff82116102df57565b9060045461ffff83169080821015610ee4578061ffff841611610ed8575b5061ffff821610610ece57610e238261ffff92610ace565b1690610e31610bb283610a67565b82815290601f19610e4184610a67565b015f5b818110610eaf5750505f5b61ffff811684811015610ea75781610e9f600192610e78610e7361ffff9688610dd7565b6109a2565b5084610e82610a10565b918054835201546020820152610e988289610b13565b5286610b13565b500116610e4f565b505050905090565b602090610eba610a10565b5f81525f8382015282828701015201610e44565b5050610d2c610d99565b61ffff1691505f610e0b565b50505050610d2c610d99565b610efa6020610a2f565b5f815290815f90815b828110610f0f57505050565b602090610f1a6109d2565b5f81525f838201525f60408201525f606082015282828501015201610f03565b919061ffff6005541661ffff8416908082101561105f578061ffff841611611057575b5061ffff82161061104c57610f758361ffff92610ace565b1691610f83610bb284610a67565b83815290601f19610f9385610a67565b015f5b8181106110215750505f5b61ffff811685811015611019579061100e6110149261ffff610fc38487610dd7565b165f52600360205260405f206002610fd96109d2565b9160ff8154818116855260081c16602084015260018101546040840152015460608201526110078288610b13565b5285610b13565b50610a54565b610fa1565b509193505050565b60209061102c6109d2565b5f81525f838201525f60408201525f606082015282828701015201610f96565b509050610d2c610ef0565b91505f610f5d565b5050509050610d2c610ef056fea2646970667358221220796ffb42b369338c4d6e13555fbcc45b5505a4b150a05579cae1e78f0fc466c364736f6c634300081e0033"},"devdoc":{"details":"Uses admin and multisig roles to control sensitive operations like asset registration and risk configuration.","kind":"dev","methods":{"addVault(uint256,bytes32)":{"details":"Reverts with `NotAdmin`; Only the admin can add a vault.","params":{"addr":"The vault address. Uses bytes32 to support non-EVM chains.","chain":"The chain ID the vault is deployed on."}},"constructor":{"details":"Sets the deployer as the initial admin.","params":{"_admin":"The admin controller of the vault."}},"getAssetData(uint64,uint16)":{"params":{"chainId":"The chain ID to query.","index":"The asset index to query."},"returns":{"_0":"The corresponding AssetData struct."}},"getAssetIndex(uint64,bytes32)":{"params":{"assetAddress":"The asset address (as bytes32).","chainId":"The chain ID to search."},"returns":{"_0":"The index of the asset, or `type(uint32).max` if not found."}},"getAssets(uint16,uint16)":{"params":{"end":"The end index (not-inclusive).","start":"The start index (inclusive)."},"returns":{"_0":"An array of AssetData structs."}},"getRiskParameters(uint16,uint16)":{"params":{"end":"The end index (not inclusive).","start":"The start index (inclusive)."},"returns":{"_0":"An array of RiskParameters."}},"getVaults(uint16,uint16)":{"params":{"end":"The end index.","start":"The start index."},"returns":{"_0":"An array of Vault."}},"setAdmin(address)":{"details":"Reverts with `NotAdmin`; Only the admin can set a new admin.Reverts if attempting to set the admin to the zero address.","params":{"newAdmin":"The new admin address."}},"setAssetData(uint16,(bytes32,uint64,uint256))":{"details":"Automatically adds new assets or chain instances if not already present.Reverts with `NotRiskManager`; Only the risk manager can set asset data.","params":{"data":"The chain-specific asset data.","index":"The asset index."}},"setCouncilMultisig(address)":{"details":"Reverts with `NotAdmin`; Only the admin can set a council.","params":{"multisig":"The new address to set."}},"setRiskManagerMultisig(address)":{"details":"Reverts with `NotAdmin`; Only the admin can set a risk manager.","params":{"multisig":"The new address to set."}},"setRiskParameters(uint16,(uint8,uint8,uint256,uint256))":{"details":"Reverts with `NotRiskManager`; Ony the risk manager can set risk parameters.Reverts with `\"!asset\"` if index >= assets.count.","params":{"index":"The asset index.","parameters":"The risk parameters to apply."}}},"title":"Registry","version":1},"methodIdentifiers":{"addVault(uint256,bytes32)":"0xca4ec14b","admin()":"0xf851a440","councilMultisig()":"0x07ddaf53","getAssetData(uint64,uint16)":"0xf247ceb9","getAssetIndex(uint64,bytes32)":"0x39006126","getAssets(uint16,uint16)":"0x0cb661c7","getRiskParameters(uint16,uint16)":"0xf0fef575","getVaults(uint16,uint16)":"0x9fd7285c","removeVault(uint256)":"0xeaadd976","riskManagerMultisig()":"0x525ea8b7","riskParameters(uint16)":"0x114bb9c5","setAdmin(address)":"0x704b6c02","setAssetData(uint16,(bytes32,uint64,uint256))":"0xc9c86796","setCouncilMultisig(address)":"0x3e112053","setRiskManagerMultisig(address)":"0x4ffcbdfb","setRiskParameters(uint16,(uint8,uint8,uint256,uint256))":"0xb6860438","vaults(uint256)":"0x8c64ea4a"},"runtimeBytecode":{"bytecode":"0x6080806040526004361015610012575f80fd5b5f3560e01c90816307ddaf5314610947575080630cb661c7146108b1578063114bb9c51461085957806339006126146108245780633e112053146107d15780634ffcbdfb1461077e578063525ea8b714610756578063704b6c02146107095780638c64ea4a146106cc5780639fd7285c14610652578063b686043814610569578063c9c86796146103f3578063ca4ec14b14610372578063eaadd9761461023a578063f0fef575146101a5578063f247ceb9146101025763f851a440146100d7575f80fd5b346100fe575f3660031901126100fe575f546040516001600160a01b039091168152602090f35b5f80fd5b346100fe5760403660031901126100fe5761011b61098c565b61ffff61012661097b565b61012e610a7e565b50165f5260066020526001600160401b0360405f2091165f52602052606060405f20600261015a6109f1565b91805483526001600160401b036001820154166020840152015460408201526101a3604051809260408091805184526001600160401b0360208201511660208501520151910152565bf35b346100fe5760403660031901126100fe576101cf6101c161096a565b6101c961097b565b90610f3a565b6040518091602082016020835281518091526020604084019201905f5b8181106101fa575050500390f35b91935091602060806001926060875160ff815116835260ff85820151168584015260408101516040840152015160608201520194019101918493926101ec565b346100fe5760203660031901126100fe575f54600435906001600160a01b03163303610363576004549081811015610330575f1982019182119190825b6102df57818110156102f357600181018082116102df57610297906109a2565b50906102a2816109a2565b6102cc578260019382036102ba575b50500182610277565b805482558301549083015584806102b1565b634e487b7160e01b5f525f60045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b600454801561031c575f1901610308816109a2565b6102cc5760015f9182815501556004555f80f35b634e487b7160e01b5f52603160045260245ffd5b60405162461bcd60e51b815260206004820152600b60248201526a6f75746f66626f756e647360a81b6044820152606490fd5b637bfa4b9f60e01b5f5260045ffd5b346100fe5760403660031901126100fe575f546001600160a01b031633036103635761039c610a10565b600435815260208101906024358252600454600160401b8110156103df578060016103ca92016004556109a2565b9290926102cc57600191518355519101555f80f35b634e487b7160e01b5f52604160045260245ffd5b346100fe5760803660031901126100fe5761040c61096a565b60603660231901126100fe576104206109f1565b6024358152604435916001600160401b03831683036100fe5760208201928352606435604083019081526001549091906001600160a01b0316330361055b5761ffff1691825f526006602052600160405f2001541590835f52600660205260405f206001600160401b0380875116165f52602052600260405f20541593855f52600660205260405f206001600160401b0380895116165f5260205260405f2092518355600183016001600160401b038851166001600160401b031982541617905551910155610545575b6104f057005b5f5260066020526001600160401b03600160405f2001915116908054600160401b8110156103df5761052791600182018155610af2565b6001600160401b03829392549160031b92831b921b19161790555f80f35b600554600181018091116102df576005556104ea565b6206732360e51b5f5260045ffd5b346100fe5760a03660031901126100fe5761058261096a565b60803660231901126100fe576105966109d2565b9060243560ff811681036100fe57825260443560ff811681036100fe57602083019081526040830160643581526060840191608435835260018060a01b0360015416330361055b5761ffff600554941693841015610624576002935f52600360205260ff60405f2095511661ff008654925160081b169161ffff191617178455516001840155519101555f80f35b60405162461bcd60e51b815260206004820152600660248201526508585cdcd95d60d21b6044820152606490fd5b346100fe5760403660031901126100fe5761067c61066e61096a565b61067661097b565b90610ded565b6040518091602082016020835281518091526020604084019201905f5b8181106106a7575050500390f35b8251805185526020908101518186015286955060409094019390920191600101610699565b346100fe5760203660031901126100fe576004356004548110156100fe576106f56040916109a2565b506001815491015482519182526020820152f35b346100fe5760203660031901126100fe576004356001600160a01b038116908190036100fe575f546001600160a01b03811633036103635781156100fe576001600160a01b031916175f55005b346100fe575f3660031901126100fe576001546040516001600160a01b039091168152602090f35b346100fe5760203660031901126100fe576004356001600160a01b038116908190036100fe575f546001600160a01b03163303610363576bffffffffffffffffffffffff60a01b60015416176001555f80f35b346100fe5760203660031901126100fe576004356001600160a01b038116908190036100fe575f546001600160a01b03163303610363576bffffffffffffffffffffffff60a01b60025416176002555f80f35b346100fe5760403660031901126100fe57602061084b61084261098c565b60243590610d3b565b63ffffffff60405191168152f35b346100fe5760203660031901126100fe5761ffff61087561096a565b165f526003602052608060405f20805490600260018201549101549060ff60405193818116855260081c16602084015260408301526060820152f35b346100fe5760403660031901126100fe576108db6108cd61096a565b6108d561097b565b90610b27565b6040518091602082016020835281518091526020604084019201905f5b818110610906575050500390f35b919350916020606082610939600194885160408091805184526001600160401b0360208201511660208501520151910152565b0194019101918493926108f8565b346100fe575f3660031901126100fe576002546001600160a01b03168152602090f35b6004359061ffff821682036100fe57565b6024359061ffff821682036100fe57565b600435906001600160401b03821682036100fe57565b6004548110156109be5760045f5260205f209060011b01905f90565b634e487b7160e01b5f52603260045260245ffd5b60405190608082018281106001600160401b038211176103df57604052565b60405190606082018281106001600160401b038211176103df57604052565b60405190604082018281106001600160401b038211176103df57604052565b6040519190601f01601f191682016001600160401b038111838210176103df57604052565b61ffff1661ffff81146102df5760010190565b6001600160401b0381116103df5760051b60200190565b610a866109f1565b905f82525f60208301525f6040830152565b610aa26020610a2f565b5f815290815f90815b828110610ab757505050565b602090610ac2610a7e565b82828501015201610aab565b9061ffff8091169116039061ffff82116102df57565b5f1981146102df5760010190565b91909180548310156109be575f52601860205f208360021c019260031b1690565b80518210156109be5760209160051b010190565b6005545f939290845b61ffff861682811015610b65575f526006602052600160405f20015481018091116102df57610b5f9095610a54565b94610b30565b5094509192909261ffff81169480861015610d1e578061ffff861611610d2f575b5061ffff841693858510610d1e5761ffff91610ba491969396610ace565b1692610bb7610bb285610a67565b610a2f565b84815290601f19610bc786610a67565b015f5b818110610d0157505f93905083805b61ffff82169680881080610cf8575b15610cec575f915b885f526006602052600160405f200154831080610ce3575b15610ccd578481101580610cc4575b610c34575b610c28610c2e91610ae4565b92610ae4565b91610bf0565b5f8981526006602052604090209097610c2e91610c2891610cbb916001600160401b0380610c658960018501610af2565b90549060031b1c16165f5260205260405f206002610c816109f1565b91805483526001600160401b03600182015416602084015201546040820152610caa828c610b13565b52610cb5818b610b13565b50610ae4565b98915050610c1c565b50858110610c17565b9992909750610cdc9150610a54565b9097610bd9565b50898810610c08565b50505050509250505090565b50888710610be8565b602090610d0f989598610a7e565b82828701015201969396610bca565b505092505050610d2c610a98565b90565b61ffff1693505f610b86565b60055490915f5b61ffff811683811015610d8c57805f52600660205260405f206001600160401b0386165f5260205260405f20548314610d845750610d7f90610a54565b610d42565b935050505090565b505050505063ffffffff90565b610da36020610a2f565b5f815290815f90815b828110610db857505050565b602090610dc3610a10565b5f81525f8382015282828501015201610dac565b9061ffff8091169116019061ffff82116102df57565b9060045461ffff83169080821015610ee4578061ffff841611610ed8575b5061ffff821610610ece57610e238261ffff92610ace565b1690610e31610bb283610a67565b82815290601f19610e4184610a67565b015f5b818110610eaf5750505f5b61ffff811684811015610ea75781610e9f600192610e78610e7361ffff9688610dd7565b6109a2565b5084610e82610a10565b918054835201546020820152610e988289610b13565b5286610b13565b500116610e4f565b505050905090565b602090610eba610a10565b5f81525f8382015282828701015201610e44565b5050610d2c610d99565b61ffff1691505f610e0b565b50505050610d2c610d99565b610efa6020610a2f565b5f815290815f90815b828110610f0f57505050565b602090610f1a6109d2565b5f81525f838201525f60408201525f606082015282828501015201610f03565b919061ffff6005541661ffff8416908082101561105f578061ffff841611611057575b5061ffff82161061104c57610f758361ffff92610ace565b1691610f83610bb284610a67565b83815290601f19610f9385610a67565b015f5b8181106110215750505f5b61ffff811685811015611019579061100e6110149261ffff610fc38487610dd7565b165f52600360205260405f206002610fd96109d2565b9160ff8154818116855260081c16602084015260018101546040840152015460608201526110078288610b13565b5285610b13565b50610a54565b610fa1565b509193505050565b60209061102c6109d2565b5f81525f838201525f60408201525f606082015282828701015201610f96565b509050610d2c610ef0565b91505f610f5d565b5050509050610d2c610ef056fea2646970667358221220796ffb42b369338c4d6e13555fbcc45b5505a4b150a05579cae1e78f0fc466c364736f6c634300081e0033"},"sourceId":"src/Registry.sol","sourcemap":"313:10239:6:-:0;;;;;;;;;;;;;-1:-1:-1;;313:10239:6;;;;-1:-1:-1;;;;;313:10239:6;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;313:10239:6;;;;;;;;-1:-1:-1;313:10239:6;;-1:-1:-1;;;;;;313:10239:6;;;;;;;;;;;;;;;;;-1:-1:-1;313:10239:6;;;;;;-1:-1:-1;313:10239:6;;;;;-1:-1:-1;313:10239:6","userdoc":{"errors":{"NotAdmin()":[{"notice":"Reverts if caller is not the admin."}],"NotRiskManager()":[{"notice":"Reverts if caller is not the risk manager multisig."}]},"kind":"user","methods":{"addVault(uint256,bytes32)":{"notice":"Register a new deposit vault contract instance."},"admin()":{"notice":"Address of the admin; primarily used for initial setup."},"constructor":{"notice":"Contract constructor."},"councilMultisig()":{"notice":"Multisig wallet address for the broader governance council."},"getAssetData(uint64,uint16)":{"notice":"Retrieves asset data for a specific asset and chain."},"getAssetIndex(uint64,bytes32)":{"notice":"Returns the asset index for a given chain and address."},"getAssets(uint16,uint16)":{"notice":"Returns all registered asset data across all chains."},"getRiskParameters(uint16,uint16)":{"notice":"Returns the full list of risk parameters for all registered assets."},"getVaults(uint16,uint16)":{"notice":"Returns the full list of registered vaults."},"riskManagerMultisig()":{"notice":"Multisig wallet address responsible for managing risk-related configurations."},"riskParameters(uint16)":{"notice":"Mapping of asset index to associated risk parameters."},"setAdmin(address)":{"notice":"Updates the admin address."},"setAssetData(uint16,(bytes32,uint64,uint256))":{"notice":"Sets or updates asset data for a specific asset index and chain."},"setCouncilMultisig(address)":{"notice":"Updates the council multisig address."},"setRiskManagerMultisig(address)":{"notice":"Updates the risk manager multisig address."},"setRiskParameters(uint16,(uint8,uint8,uint256,uint256))":{"notice":"Sets risk parameters for a specific asset index."},"vaults(uint256)":{"notice":"All registered vaults."}},"notice":"Central registry for managing assets and associated risk parameters across multiple chains.","version":1}},"SigTest":{"abi":[{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"check","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"contractName":"SigTest","deploymentBytecode":{"bytecode":"0x608080604052346015576101c9908161001a8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c63197ff59b14610024575f80fd5b346100a35760603660031901126100a3576004356001600160a01b03811681036100a35760443567ffffffffffffffff81116100a357366023820112156100a357806004013567ffffffffffffffff81116100a35736602482840101116100a3576020926024610099930190602435906100a7565b6040519015158152f35b5f80fd5b92939290915f906001600160a01b0383161561018a576040519160048301602484019560448501916064860193873b156101115750936064938a80948a9b9c9460209b9a9998630b135d3f60e11b8a525260408a52523701915afa9051630b135d3f60e11b141690565b99935050939550508060401461015e5760411461012e5750505050565b60408092939496508101355f1a60205281375b5f526020600160805f825afa511860601b3d11915f606052604052565b5060208082013560ff81901c601b0190915290356040526001600160ff1b031660605291935090610141565b505f945050505056fea26469706673582212208a106949f349498c2239c8e95c70bad1b3b3e62a5294423000b592793b14c09564736f6c634300081c0033"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"check(address,bytes32,bytes)":"0x197ff59b"},"runtimeBytecode":{"bytecode":"0x60806040526004361015610011575f80fd5b5f3560e01c63197ff59b14610024575f80fd5b346100a35760603660031901126100a3576004356001600160a01b03811681036100a35760443567ffffffffffffffff81116100a357366023820112156100a357806004013567ffffffffffffffff81116100a35736602482840101116100a3576020926024610099930190602435906100a7565b6040519015158152f35b5f80fd5b92939290915f906001600160a01b0383161561018a576040519160048301602484019560448501916064860193873b156101115750936064938a80948a9b9c9460209b9a9998630b135d3f60e11b8a525260408a52523701915afa9051630b135d3f60e11b141690565b99935050939550508060401461015e5760411461012e5750505050565b60408092939496508101355f1a60205281375b5f526020600160805f825afa511860601b3d11915f606052604052565b5060208082013560ff81901c601b0190915290356040526001600160ff1b031660605291935090610141565b505f945050505056fea26469706673582212208a106949f349498c2239c8e95c70bad1b3b3e62a5294423000b592793b14c09564736f6c634300081c0033"},"sourceId":"src/SigTest.sol","sourcemap":"140:221:1:-:0;;;;;;;;;;;;;;;;;","userdoc":{"kind":"user","methods":{},"version":1}}},"manifest":"ethpm/3","sources":{"src/Checkpointer.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.28;\n\nimport {EfficientHashLib} from \"solady/utils/EfficientHashLib.sol\";\nimport {SignatureCheckerLib} from \"solady/utils/SignatureCheckerLib.sol\";\n\n/**\n * @title Checkpointer\n * @notice Tracks and validates state root checkpoints using EIP-712 signatures from admin and leader nodes.\n * @dev Designed for use in DStack-like distributed settlement systems.\n */\ncontract Checkpointer {\n /**\n * @notice Address with the authority to set initial parameters.\n * @dev Should be set to the DStack app shared secret public key.\n */\n address public admin;\n\n /**\n * @notice Public key of the current designated leader node.\n * @dev Leader is responsible for signing and submitting new checkpoints.\n */\n address public leader;\n\n /**\n * @notice Gnosis Safe address used as the council multisig.\n * @dev Can rotate the leader and self.\n */\n address public councilMultisig;\n\n /**\n * @notice Monotonically increasing nonce for checkpoint submissions.\n * @dev Used to prevent replay attacks and enforce checkpoint ordering.\n */\n uint256 public stateRootNonce;\n\n /// @notice Typehash used for EIP-712 encoding of the Checkpoint struct.\n bytes32 public constant CHECKPOINT_TYPEHASH =\n keccak256(\"Checkpoint(uint256 nonce,uint8[] stateRoot,string[] approvedWithdrawals)\");\n\n /**\n * @notice Emitted when a new list of approved withdrawals is recorded in a checkpoint.\n * @param approvedWithdrawals List of withdrawal IDs approved in the checkpoint.\n */\n event Withdrawals(string[] approvedWithdrawals);\n\n /// @notice Cached domain separator for EIP-712 signature verification.\n bytes32 internal _domainSeparator;\n\n /**\n * @notice The current state root, encoded as a serialized vector.\n * @dev Serialized as `(user, eth_balance, usdc_balance, deposit_nonce, is_mm)` tuples.\n * In production, this may store multiple roots and rotate.\n */\n uint8[] public stateRoot;\n\n /// @notice Reverts if caller is not the admin.\n error NotAdmin();\n\n /// @notice Reverts if a value has already been set.\n error AlreadySet();\n\n /// @notice Reverts if caller is not the current council multisig.\n error NotCouncilMultisig();\n\n /// @notice Reverts if a signature does not match the expected signer or payload.\n error InvalidSignature();\n\n /**\n * @notice Contract constructor.\n * @dev Sets the deployer as the initial admin.\n */\n constructor() {\n admin = msg.sender;\n }\n\n /**\n * @notice Sets the EIP-712 domain separator used for verifying signatures.\n * @param domainSeparator The domain separator to store.\n */\n function setDomainSeparator(bytes32 domainSeparator) external {\n if (msg.sender != admin) revert NotAdmin();\n if (_domainSeparator != 0) revert AlreadySet();\n _domainSeparator = domainSeparator;\n }\n\n /**\n * @notice Transfers admin control to a new address.\n * @param newAdmin The new admin address.\n */\n function setAdmin(address newAdmin) external {\n if (msg.sender != admin) revert NotAdmin();\n require(newAdmin != address(0));\n admin = newAdmin;\n }\n\n /**\n * @notice Sets the initial council multisig address.\n * @param newCouncilMultisig The council's Gnosis Safe address.\n */\n function setInitialCouncilMultisig(address newCouncilMultisig) external {\n if (msg.sender != admin) revert NotAdmin();\n if (councilMultisig != address(0)) revert AlreadySet();\n councilMultisig = newCouncilMultisig;\n }\n\n /**\n * @notice Allows the current council to rotate itself to a new address.\n * @param newCouncilMultisig The new multisig address.\n */\n function setNewCouncilMultisig(address newCouncilMultisig) external {\n if (msg.sender != councilMultisig) revert NotCouncilMultisig();\n councilMultisig = newCouncilMultisig;\n }\n\n /**\n * @notice Sets the leader node address.\n * @dev This should be reviewed depending on the leader rotation mechanism.\n * @param newLeader The address of the new leader node.\n */\n function setLeader(address newLeader) external {\n if (msg.sender != councilMultisig) revert NotCouncilMultisig();\n leader = newLeader;\n }\n\n /**\n * @notice Checkpoint submitted by a node to update the system state.\n * @dev Requires valid EIP-712 signatures from both admin and leader.\n * @param sharedSignature Signature by the admin.\n * @param leaderSignature Signature by the leader.\n * @param _checkpoint The checkpoint payload to commit.\n */\n function checkpoint(\n bytes calldata sharedSignature,\n bytes calldata leaderSignature,\n Checkpoint calldata _checkpoint\n ) external {\n require(_checkpoint.nonce == stateRootNonce); // dev: Nonce mismatch\n\n // Compute the EIP-712 struct hash.\n bytes32 structHash = EfficientHashLib.hash(\n abi.encode(\n CHECKPOINT_TYPEHASH,\n _checkpoint.nonce,\n EfficientHashLib.hash(abi.encodePacked(_checkpoint.stateRoot)),\n hashStringArray(_checkpoint.approvedWithdrawals)\n )\n );\n\n // Check both admin and leader signatures.\n bytes32 digest =\n EfficientHashLib.hash(abi.encodePacked(\"\\x19\\x01\", _domainSeparator, structHash));\n\n if (!SignatureCheckerLib.isValidSignatureNow(admin, digest, sharedSignature)) {\n revert InvalidSignature();\n }\n\n if (!SignatureCheckerLib.isValidSignatureNow(leader, digest, leaderSignature)) {\n revert InvalidSignature();\n }\n\n stateRootNonce++;\n stateRoot = _checkpoint.stateRoot;\n\n emit Withdrawals(_checkpoint.approvedWithdrawals);\n }\n\n /**\n * @notice Internal helper for hashing an array of strings.\n * @dev Each string is hashed individually and packed before final hashing.\n * @param arr The array of strings to hash.\n * @return A single keccak256 hash of the packed array of hashed strings.\n */\n function hashStringArray(string[] memory arr) internal pure returns (bytes32) {\n bytes32[] memory hashedStrings = new bytes32[](arr.length);\n for (uint256 i = 0; i < arr.length; i++) {\n hashedStrings[i] = EfficientHashLib.hash(bytes(arr[i]));\n }\n return EfficientHashLib.hash(abi.encodePacked(hashedStrings));\n }\n\n /**\n * @notice Struct defining a checkpoint message.\n * @dev Checkpoints include the current state root, a nonce, and a list of approved withdrawals.\n */\n struct Checkpoint {\n uint256 nonce;\n uint8[] stateRoot;\n string[] approvedWithdrawals;\n }\n}\n","urls":[]},"src/DepositVault.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.28;\n\nimport {SafeTransferLib} from \"solady/utils/SafeTransferLib.sol\";\nimport {EfficientHashLib} from \"solady/utils/EfficientHashLib.sol\";\nimport {ECDSA} from \"solady/utils/ECDSA.sol\";\nimport {IAtomicSettlementCallback} from \"./interfaces/IAtomicSettlementCallback.sol\";\n\ncontract DepositVault {\n /**\n * @notice The admin approves settlements and withdrawals.\n * @dev Should be set to the DStack container shared secret address.\n */\n address public owner;\n\n /// @notice EIP-712 domain separator used for signature verification.\n bytes32 internal _domainSeparator;\n\n /// @notice Maps settler IDs to their executor addresses.\n mapping(bytes32 => SettlerInfo) settlerExecutorMap;\n\n /// @notice List of all approved settler IDs.\n bytes32[] public approvedSettlers;\n\n /// @notice Tracks which settler IDs have been approved.\n mapping(bytes32 => bool) internal settlerIsApproved;\n\n /**\n * @notice Maximum total tokens that can be settled in a single block for each token.\n * @dev Currently unused \u2014 implementation pending design finalization.\n */\n mapping(address => uint256) public settlementCaps;\n\n /// @notice Maps settler IDs to their queue of pending batch settlements.\n mapping(bytes32 => PendingSettlement[]) public pendingSettlements;\n\n /// @notice Maps settler IDs to their settlement count (nonce).\n mapping(bytes32 => uint256) public settlementCounts;\n\n /// @notice Maps settler IDs to their deposit count (nonce).\n mapping(bytes32 => uint256) public depositCounts;\n\n /// @notice Maps settler IDs to their withdrawal count (nonce).\n mapping(bytes32 => uint256) public withdrawalCounts;\n\n /// @notice True for any valid authority; used in settlement/withdrawal signature verification.\n mapping(address => bool) public isAdmin;\n\n // TODO: Delete before official production.\n mapping(address => bool) public canDeposit;\n\n /**\n * @notice EIP-712 typehash for an Order struct used in off-chain signature verification.\n * @dev ORDER_TYPEHASH = keccak256(\"Order(address tokenOut,uint256 amountOut,address tokenIn,uint256 amountIn,bytes32 user,uint256 nonce,uint256 validUntil)\");\n */\n bytes32 public constant ORDER_TYPEHASH =\n 0x3a0cb10b78ebd9ca317b25e5ca18c0e451c56fb5d187fc2f8745cb1b6834d318;\n\n /**\n * @notice A single settlement request for token swaps.\n * @dev Used in both atomic and batch settlements.\n */\n struct Settlement {\n address tokenOut;\n uint256 amountOut;\n address tokenIn;\n uint256 amountIn;\n uint256 nonce;\n }\n\n /// @notice A settlement plus an off-chain signature from an authorized party.\n struct SignedSettlement {\n Settlement settlement;\n bytes signature;\n }\n\n /**\n * @notice Stores pending settlements for a given user when batch settlement is used.\n * @dev Target is the address expected to execute the settlement.\n */\n struct PendingSettlement {\n Settlement settlement;\n address target;\n }\n\n /// @notice Records a withdrawal.\n struct Withdrawal {\n address tokenAddress;\n uint256 amount;\n uint256 nonce;\n }\n\n /// @notice Information about a settler account.\n struct SettlerInfo {\n address[] executors;\n mapping(address => bool) isExecutor;\n }\n\n /// @notice Signals a settlement.\n event Settled(\n bytes32 indexed user,\n uint256 indexed nonce,\n address tokenOut,\n uint256 amountOut,\n address tokenIn,\n uint256 amountIn\n );\n\n /// @notice Signals a deposit.\n event Deposited(\n bytes32 indexed user, uint256 indexed nonce, address tokenAddress, uint256 amount\n );\n\n /// @notice Signals a withdrawal.\n event Withdrew(\n bytes32 indexed user, uint256 indexed nonce, address tokenAddress, uint256 amount\n );\n\n /// @notice Reverts if the caller is not the owner.\n error NotOwner();\n\n /// @notice Reverts if the caller is not an admin.\n error NotAdmin();\n\n /// @notice Reverts if the caller is not the authorized executor.\n error NotExecutor();\n\n /// @notice Reverts if a signed operation is past its deadline.\n error Expired();\n\n /// @notice Reverts if the nonce used in a transaction is incorrect.\n error InvalidNonce(uint256 expected, uint256 given);\n\n /// @notice Reverts if the signature provided is invalid.\n error InvalidSignature();\n\n /// @notice Reverts if an order array is empty.\n error EmptyOrders();\n\n /**\n * @notice Initializes the contract and sets the owner. Also permits the owner to authorize\n * settlements and withdrawals.\n * @param _owner The address to set as the owner.\n */\n constructor(address _owner, bytes32 domainSeparator) {\n require(_owner != address(0), \"Invalid owner\");\n owner = _owner;\n isAdmin[_owner] = true;\n _domainSeparator = domainSeparator;\n }\n\n /**\n * @notice Sets the owner of the vault.\n * @dev Reverts with `NotOwner`; Only the owner can set a new owner.\n */\n function setOwner(address newOwner) external {\n if (msg.sender != owner) revert NotOwner();\n require(newOwner != address(0));\n owner = newOwner;\n }\n\n /**\n * @notice Sets the domain separators for EIP-712 signatures.\n * @param domainSeparator: The value to set.\n * @dev Reverts with `NotOwner`; Only the admin can set the domain separator.\n */\n function setDomainSeparator(bytes32 domainSeparator) external {\n if (msg.sender != owner) revert NotOwner();\n require(_domainSeparator == 0); // dev: Already set.\n _domainSeparator = domainSeparator;\n }\n\n /**\n * @notice Sets the settle executor.\n * @param settler: The settler's tplus account key.\n * @param executor: The settler's assigned executor address.\n * @dev Reverts with `NotOwner`; Only the admin can set the settler executor.\n */\n function addSettlerExecutor(bytes32 settler, address executor) external {\n if (msg.sender != owner) revert NotOwner();\n if (!settlerIsApproved[settler]) {\n approvedSettlers.push(settler);\n settlerIsApproved[settler] = true;\n }\n\n settlerExecutorMap[settler].executors.push(executor);\n settlerExecutorMap[settler].isExecutor[executor] = true;\n }\n\n /**\n * @notice Removes a settler.\n * @param settler: The settler's tplus account key.\n * @dev Reverts with `NotOwner`; Only the admin can remove a settler.\n */\n function removeSettler(bytes32 settler) external {\n if (msg.sender != owner) revert NotOwner();\n uint256 length = approvedSettlers.length;\n for (uint256 i = 0; i < length; i++) {\n if (approvedSettlers[i] == settler) {\n // Move last element to this spot and pop the last element.\n approvedSettlers[i] = approvedSettlers[length - 1];\n approvedSettlers.pop();\n break;\n }\n }\n\n // Remove all executors.\n SettlerInfo storage info = settlerExecutorMap[settler];\n for (uint256 i = 0; i < info.executors.length; i++) {\n address exec = info.executors[i];\n info.isExecutor[exec] = false;\n }\n delete info.executors;\n }\n\n /**\n * @notice Grants or revokes settlement and withdrawal approval rights to an address.\n * @param account The address to grant or revoke approval rights.\n * @param authorized Whether the account is authorized to approve settlements/withdrawals.\n * @dev Reverts with `NotOwner` if called by an address other than the admin.\n */\n function setAdmin(address account, bool authorized) external {\n if (msg.sender != owner) revert NotOwner();\n isAdmin[account] = authorized;\n }\n\n /**\n * @notice Deposits a token into the vault.\n * @param user: The user whose account will be credited with the deposit.\n * @param tokenAddress: The address of the token to deposit.\n * @param amount: The amount of the token to deposit.\n * @dev Reverts if the amount is 0.\n */\n function deposit(bytes32 user, address tokenAddress, uint256 amount) external {\n require(canDeposit[msg.sender], \"!depositor\");\n require(amount != 0, \"Zero\");\n\n // Move tokens from the target user to this vault.\n SafeTransferLib.safeTransferFrom(tokenAddress, msg.sender, address(this), amount);\n\n emit Deposited(user, depositCounts[user], tokenAddress, amount);\n depositCounts[user] += 1;\n }\n\n // TODO: Delete this method and notion of approved-depositor before official production.\n function setDepositorStatus(address depositor, bool allowed) external {\n if (msg.sender != owner) revert NotOwner();\n canDeposit[depositor] = allowed;\n }\n\n /**\n * @notice Executes an atomic settlement.\n * @param order: The settlement order.\n * @param user: The t+ user who is executing the settlement.\n * @param validUntil: How long until the signature expires.\n * @param data: The data to execute as part of settlement callback.\n * @param signature: The signature from the t+ clearing engine.\n * @dev Reverts with `Expired` if the block timestamp is greater than `validUntil`.\n * @dev Reverts with `NotExecutor`; Only the executor can settle.\n * @dev Reverts with `InvalidNonce` if the nonce has already been used.\n * @dev Reverts with `SignatureError` if the signer is not an admin.\n */\n function executeAtomicSettlement(\n Settlement calldata order,\n bytes32 user,\n uint256 validUntil,\n bytes calldata data,\n bytes calldata signature\n ) external {\n if (block.timestamp > validUntil) revert Expired();\n if (!settlerExecutorMap[user].isExecutor[msg.sender]) revert NotExecutor();\n\n uint256 expectedNonce = settlementCounts[user];\n if (order.nonce != expectedNonce) revert InvalidNonce(expectedNonce, order.nonce);\n\n bytes32 domainSeparator = _domainSeparator;\n\n bytes32 structHash = EfficientHashLib.hash(\n abi.encode(\n ORDER_TYPEHASH,\n order.tokenOut,\n order.amountOut,\n order.tokenIn,\n order.amountIn,\n user,\n order.nonce,\n validUntil\n )\n );\n\n bytes32 digest =\n EfficientHashLib.hash(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n\n checkApproval(digest, signature);\n\n SafeTransferLib.safeTransfer(order.tokenOut, msg.sender, order.amountOut);\n\n // Ensure to bump the nonce _before_ the callback to avoid signature replay.\n settlementCounts[user] += 1;\n\n IAtomicSettlementCallback(msg.sender)\n .onAtomicSettlement(order.tokenOut, order.amountOut, data);\n SafeTransferLib.safeTransferFrom(order.tokenIn, msg.sender, address(this), order.amountIn);\n\n emit Settled(\n user, order.nonce, order.tokenOut, order.amountOut, order.tokenIn, order.amountIn\n );\n }\n\n /**\n * @notice Pulls funds for execution during a settlement batch.\n * @param orders: The settlement orders.\n * @param user: The t+ user who is executing the settlement.\n * @param target: The target address to send the token to, pull tokens from, and execute callback on.\n * @param validUntil: The timestamp when the settlement signature expires.\n * @dev Reverts with `Expired` if the block timestamp is greater than `validUntil`.\n * @dev Reverts if a batch settlement has already started.\n * @dev Reverts with `NotAdmin`; Only an admin can execute the settlement.\n * @dev Reverts with `InvalidNonce` if the nonce has already been used.\n * @dev Reverts with `SignatureError` if the signer is not an admin.\n */\n function pullBatchSettlement(\n SignedSettlement[] calldata orders,\n bytes32 user,\n address target,\n uint256 validUntil\n ) external {\n if (block.timestamp > validUntil) revert Expired();\n require(pendingSettlements[user].length == 0); // dev: Already started.\n if (!isAdmin[msg.sender]) revert NotAdmin();\n\n uint256 expectedNonce = settlementCounts[user];\n bytes32 domainSeparator = _domainSeparator;\n uint256 ordersLength = orders.length;\n if (ordersLength == 0) revert EmptyOrders();\n\n // Unchecked is OK to use to save gas on the for loops.\n unchecked {\n for (uint256 i = 0; i < ordersLength; ++i) {\n Settlement calldata s = orders[i].settlement;\n\n uint256 nonce = s.nonce;\n if (nonce != expectedNonce) revert InvalidNonce(expectedNonce, nonce);\n\n bytes32 structHash = EfficientHashLib.hash(\n abi.encode(\n ORDER_TYPEHASH,\n s.tokenOut,\n s.amountOut,\n s.tokenIn,\n s.amountIn,\n user,\n nonce,\n validUntil\n )\n );\n\n bytes32 digest = EfficientHashLib.hash(\n abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash)\n );\n\n checkApproval(digest, orders[i].signature);\n pendingSettlements[user].push(PendingSettlement({settlement: s, target: target}));\n SafeTransferLib.safeTransfer(s.tokenOut, target, s.amountOut);\n\n expectedNonce = nonce + 1;\n }\n }\n\n settlementCounts[user] += ordersLength;\n }\n\n /**\n * @notice Pushes expected funds from a batch settlement to the deposit vault.\n * @param user: The t+ user who is executing the settlement.\n * @dev Reverts with `NotAdmin`; Only an admin can execute the settlement.\n */\n function pushBatchSettlements(bytes32 user) external {\n if (!isAdmin[msg.sender]) revert NotAdmin();\n\n for (uint32 i = 0; i < pendingSettlements[user].length; i++) {\n PendingSettlement memory pendingSettlement = pendingSettlements[user][i];\n\n SafeTransferLib.safeTransferFrom(\n pendingSettlement.settlement.tokenIn,\n pendingSettlement.target,\n address(this),\n pendingSettlement.settlement.amountIn\n );\n emit Settled(\n user,\n pendingSettlement.settlement.nonce,\n pendingSettlement.settlement.tokenOut,\n pendingSettlement.settlement.amountOut,\n pendingSettlement.settlement.tokenIn,\n pendingSettlement.settlement.amountIn\n );\n }\n delete pendingSettlements[user];\n }\n\n /**\n * @notice Withdraws a token from the vault.\n * @param withdrawal: The withdrawal token and amount.\n * @param user: The user whose account will be debited by the withdrawal.\n * @param target: The target address to send the token to.\n * @param validUntil: The timestamp when the withdrawal signature expires.\n * @param signature: t+ clearing engine signature.\n * @dev Reverts with `Expired` if the block timestamp is greater than `validUntil`.\n * @dev Reverts with `InvalidNonce` if the nonce has already been used.\n * @dev Reverts with `SignatureError` if the signer is not an admin.\n */\n function withdraw(\n Withdrawal calldata withdrawal,\n bytes32 user,\n address target,\n uint256 validUntil,\n bytes calldata signature\n ) external {\n if (block.timestamp > validUntil) revert Expired();\n\n uint256 expectedNonce = withdrawalCounts[user];\n if (withdrawal.nonce != expectedNonce) {\n revert InvalidNonce(expectedNonce, withdrawal.nonce);\n }\n\n // NOTE: This is intentionally not EIP-712 compliant (it is just purposely similar as well).\n // Reason: Unnecessary extra computation; not signed by an actual wallet.\n checkApproval(\n EfficientHashLib.hash(\n abi.encodePacked(\n _domainSeparator,\n withdrawal.tokenAddress,\n withdrawal.amount,\n user,\n withdrawal.nonce,\n validUntil\n )\n ),\n signature\n );\n\n SafeTransferLib.safeTransfer(withdrawal.tokenAddress, target, withdrawal.amount);\n emit Withdrew(user, withdrawal.nonce, withdrawal.tokenAddress, withdrawal.amount);\n withdrawalCounts[user] += 1;\n }\n\n /**\n * @notice Get the array of approved settlers.\n * @return An array of addresses (as bytes32) that are currently approved settlers.\n */\n function getApprovedSettlers() external view returns (bytes32[] memory) {\n return approvedSettlers;\n }\n\n // TODO: Delete this method before official production.\n function ownerWithdrawToken(address token, address to, uint256 amount) external {\n if (msg.sender != owner) revert NotOwner();\n require(to != address(0));\n SafeTransferLib.safeTransfer(token, to, amount);\n }\n\n function checkApproval(bytes32 digest, bytes calldata signature) internal view {\n address signer = ECDSA.tryRecoverCalldata(digest, signature);\n if (!isAdmin[signer]) revert InvalidSignature();\n }\n}\n","urls":[]},"src/Registry.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.28;\n\n/**\n * @title Registry\n * @notice Central registry for managing assets and associated risk parameters across multiple chains.\n * @dev Uses admin and multisig roles to control sensitive operations like asset registration and risk configuration.\n */\ncontract Registry {\n /// @notice Address of the admin; primarily used for initial setup.\n address public admin;\n\n /// @notice Multisig wallet address responsible for managing risk-related configurations.\n address public riskManagerMultisig;\n\n /// @notice Multisig wallet address for the broader governance council.\n address public councilMultisig;\n\n /// @notice Mapping of asset index to associated risk parameters.\n mapping(uint16 => RiskParameters) public riskParameters;\n\n /// @notice All registered vaults.\n Vault[] public vaults;\n\n /// @notice Registry of all registered assets and associated chain data.\n AssetRegistry assets;\n\n /// @notice Struct defining risk-related parameters for a given asset.\n struct RiskParameters {\n uint8 collateralFactor;\n uint8 liabilityFactor;\n uint256 maxCollateral; // Optional: may not be enforced on-chain.\n uint256 maxLiabilities; // Optional: may not be enforced on-chain.\n }\n\n /**\n * @notice Struct for managing a list of registered assets.\n * @dev Assets are stored by index and can span multiple chains.\n */\n struct AssetRegistry {\n uint256 count; // Total number of assets.\n mapping(uint16 => Asset) registry; // Mapping from index to asset struct.\n }\n\n /**\n * @notice Struct representing an asset across multiple chains.\n */\n struct Asset {\n mapping(uint64 => AssetData) data; // Chain ID => AssetData.\n uint64[] chains; // List of all known chain IDs for this asset.\n }\n\n /**\n * @notice Chain-specific metadata for an asset.\n * @dev Uses bytes32 for `assetAddress` to support non-EVM chains like Solana.\n */\n struct AssetData {\n bytes32 assetAddress;\n uint64 chainId;\n uint256 maxDeposits; // Cap on deposits (collateral cap).\n }\n\n /**\n * @notice A registered official vault contract on any chain.\n * @dev Uses bytes32 for `assetAddress` to support non-EVM chains like Solana.\n */\n struct Vault {\n uint256 chain;\n // NOTE: Using 'bytes32' instead of 'address' because the vault may be deployed on\n // a change with larger address sizes, such as Solana.\n bytes32 vaultAddress;\n }\n\n /// @notice Reverts if caller is not the admin.\n error NotAdmin();\n\n /// @notice Reverts if caller is not the risk manager multisig.\n error NotRiskManager();\n\n /**\n * @notice Contract constructor.\n * @param _admin The admin controller of the vault.\n * @dev Sets the deployer as the initial admin.\n */\n constructor(address _admin) {\n admin = _admin;\n }\n\n /**\n * @notice Updates the risk manager multisig address.\n * @param multisig The new address to set.\n * @dev Reverts with `NotAdmin`; Only the admin can set a risk manager.\n */\n function setRiskManagerMultisig(address multisig) external {\n if (msg.sender != admin) revert NotAdmin();\n riskManagerMultisig = multisig;\n }\n\n /**\n * @notice Updates the council multisig address.\n * @param multisig The new address to set.\n * @dev Reverts with `NotAdmin`; Only the admin can set a council.\n */\n function setCouncilMultisig(address multisig) external {\n if (msg.sender != admin) revert NotAdmin();\n councilMultisig = multisig;\n }\n\n /**\n * @notice Updates the admin address.\n * @param newAdmin The new admin address.\n * @dev Reverts with `NotAdmin`; Only the admin can set a new admin.\n * @dev Reverts if attempting to set the admin to the zero address.\n */\n function setAdmin(address newAdmin) external {\n if (msg.sender != admin) revert NotAdmin();\n require(newAdmin != address(0));\n admin = newAdmin;\n }\n\n /**\n * @notice Sets or updates asset data for a specific asset index and chain.\n * @dev Automatically adds new assets or chain instances if not already present.\n * @param index The asset index.\n * @param data The chain-specific asset data.\n * @dev Reverts with `NotRiskManager`; Only the risk manager can set asset data.\n */\n function setAssetData(uint16 index, AssetData memory data) external {\n if (msg.sender != riskManagerMultisig) revert NotRiskManager();\n\n bool isNewAsset = assets.registry[index].chains.length <= 0;\n bool isNewAddress = assets.registry[index].data[data.chainId].assetAddress == bytes32(0);\n\n assets.registry[index].data[data.chainId] = data;\n\n if (isNewAsset) {\n assets.count += 1;\n }\n if (isNewAddress) {\n assets.registry[index].chains.push(data.chainId);\n }\n }\n\n /**\n * @notice Retrieves asset data for a specific asset and chain.\n * @param chainId The chain ID to query.\n * @param index The asset index to query.\n * @return The corresponding AssetData struct.\n */\n function getAssetData(uint64 chainId, uint16 index) external view returns (AssetData memory) {\n return assets.registry[index].data[chainId];\n }\n\n /**\n * @notice Returns all registered asset data across all chains.\n * @return An array of AssetData structs.\n * @param start The start index (inclusive).\n * @param end The end index (not-inclusive).\n */\n function getAssets(uint16 start, uint16 end) external view returns (AssetData[] memory) {\n // First, compute the total flattened entries\n uint256 totalEntries = 0;\n for (uint16 i = 0; i < assets.count; i++) {\n totalEntries += assets.registry[i].chains.length;\n }\n\n // Return empty array if start >= totalEntries\n if (start >= totalEntries) {\n return new AssetData[](0);\n }\n\n if (end > totalEntries) {\n // casting to 'uint16' is safe because we won't ever that many assets.\n // forge-lint: disable-next-line(unsafe-typecast)\n end = uint16(totalEntries);\n }\n\n if (end < start) {\n return new AssetData[](0);\n }\n\n uint16 length = end - start;\n AssetData[] memory result = new AssetData[](length);\n\n uint256 r = 0;\n uint256 resIdx = 0;\n\n for (uint16 i = 0; i < assets.count && resIdx < length; i++) {\n for (uint256 c = 0; c < assets.registry[i].chains.length && resIdx < length; c++) {\n if (r >= start && r < end) {\n result[resIdx] = assets.registry[i].data[assets.registry[i].chains[c]];\n resIdx++;\n }\n r++;\n }\n }\n\n return result;\n }\n\n /**\n * @notice Returns the asset index for a given chain and address.\n * @param chainId The chain ID to search.\n * @param assetAddress The asset address (as bytes32).\n * @return The index of the asset, or `type(uint32).max` if not found.\n */\n function getAssetIndex(uint64 chainId, bytes32 assetAddress) external view returns (uint32) {\n for (uint16 i = 0; i < assets.count; i++) {\n if (assetAddress == assets.registry[i].data[chainId].assetAddress) {\n return i;\n }\n }\n return type(uint32).max;\n }\n\n /**\n * @notice Sets risk parameters for a specific asset index.\n * @param index The asset index.\n * @param parameters The risk parameters to apply.\n * @dev Reverts with `NotRiskManager`; Ony the risk manager can set risk parameters.\n * @dev Reverts with `\"!asset\"` if index >= assets.count.\n */\n function setRiskParameters(uint16 index, RiskParameters memory parameters) external {\n if (msg.sender != riskManagerMultisig) revert NotRiskManager();\n require(index < assets.count, \"!asset\");\n riskParameters[index] = parameters;\n }\n\n /**\n * @notice Returns the full list of risk parameters for all registered assets.\n * @return An array of RiskParameters.\n * @param start The start index (inclusive).\n * @param end The end index (not inclusive).\n */\n function getRiskParameters(uint16 start, uint16 end)\n external\n view\n returns (RiskParameters[] memory)\n {\n uint16 count = uint16(assets.count);\n\n if (start >= count) {\n return new RiskParameters[](0);\n }\n\n if (end > count) {\n end = count;\n }\n\n if (end < start) {\n return new RiskParameters[](0);\n }\n\n uint256 length = end - start;\n RiskParameters[] memory result = new RiskParameters[](length);\n\n for (uint16 i = 0; i < length; ++i) {\n result[i] = riskParameters[start + i];\n }\n\n return result;\n }\n\n /**\n * @notice Register a new deposit vault contract instance.\n * @param chain The chain ID the vault is deployed on.\n * @param addr The vault address. Uses bytes32 to support non-EVM chains.\n * @dev Reverts with `NotAdmin`; Only the admin can add a vault.\n */\n function addVault(uint256 chain, bytes32 addr) external {\n if (msg.sender != admin) revert NotAdmin();\n vaults.push(Vault({chain: chain, vaultAddress: addr}));\n }\n\n // TODO: We probably don't want this method once we are officially live; vault should never be removed.\n function removeVault(uint256 idx) external {\n if (msg.sender != admin) revert NotAdmin();\n uint256 length = vaults.length;\n require(idx < length, \"outofbounds\");\n\n // Shift elements left\n for (uint256 i = idx; i < length - 1; i++) {\n vaults[i] = vaults[i + 1];\n }\n vaults.pop();\n }\n\n /**\n * @notice Returns the full list of registered vaults.\n * @return An array of Vault.\n * @param start The start index.\n * @param end The end index.\n */\n function getVaults(uint16 start, uint16 end) external view returns (Vault[] memory) {\n uint256 count = vaults.length;\n\n if (start >= count) {\n return new Vault[](0);\n }\n\n if (end > count) {\n // casting to 'uint16' is safe because we won't ever have too many vaults.\n // forge-lint: disable-next-line(unsafe-typecast)\n end = uint16(count);\n }\n\n if (end < start) {\n return new Vault[](0);\n }\n\n uint16 length = end - start;\n Vault[] memory result = new Vault[](length);\n\n for (uint16 i = 0; i < length; ++i) {\n result[i] = vaults[start + i];\n }\n\n return result;\n }\n}\n","urls":[]},"src/interfaces/IAtomicSettlementCallback.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.28;\n\ninterface IAtomicSettlementCallback {\n function onAtomicSettlement(address token, uint256 amount, bytes calldata data) external;\n}\n","urls":[]}}} \ No newline at end of file +{"compilers":[{"contractTypes":["SigTest","MockTarget"],"name":"solidity","settings":{"optimizer":{"enabled":true,"runs":200},"outputSelection":{"src/.cache/solady/main/src/utils/ECDSA.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/solady/main/src/utils/EfficientHashLib.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/solady/main/src/utils/SafeTransferLib.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]}},"remappings":["solady=src/.cache/solady/main/src"],"viaIR":true},"version":"0.8.28+commit.7893614a"},{"contractTypes":["IL1CrossDomainMessenger","IDepositVault","SignatureTest","Settler","IAtomicSettlementCallback","ICheckpointer","DepositVault","Registry","ICredentialManager","OPStackAdminUpdateStrategy","ArbitrumOneAdminUpdateStrategy","Checkpointer","IRegistry","CredentialManager","IAdminUpdateStrategy","IAutomataDcapAttestation","IntraChainAdminUpdateStrategy"],"name":"solidity","settings":{"optimizer":{"enabled":true,"runs":200},"outputSelection":{"src/.cache/nitro-contracts/main/src/bridge/DelayBufferTypes.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/nitro-contracts/main/src/bridge/IBridge.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/nitro-contracts/main/src/bridge/IDelayedMessageProvider.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/nitro-contracts/main/src/bridge/IInbox.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/nitro-contracts/main/src/bridge/IInboxBase.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/nitro-contracts/main/src/bridge/IOwnable.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/nitro-contracts/main/src/bridge/ISequencerInbox.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/nitro-contracts/main/src/bridge/Messages.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/nitro-contracts/main/src/libraries/IGasRefunder.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/solady/main/src/utils/ECDSA.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/solady/main/src/utils/EfficientHashLib.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/solady/main/src/utils/SafeTransferLib.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/.cache/solady/main/src/utils/SignatureCheckerLib.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/Checkpointer.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/CredentialManager.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/DepositVault.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/Registry.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/interfaces/IAdminUpdateStrategy.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/interfaces/IAtomicSettlementCallback.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/interfaces/IAutomataDcapAttestation.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/interfaces/ICheckpointer.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/interfaces/ICredentialManager.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/interfaces/IDepositVault.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/interfaces/IRegistry.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/strategies/ArbitrumOneAdminUpdateStrategy.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/strategies/IntraChainAdminUpdateStrategy.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]},"src/strategies/OPStackAdminUpdateStrategy.sol":{"":["ast"],"*":["abi","bin-runtime","devdoc","userdoc","evm.bytecode.object","evm.bytecode.sourceMap","evm.deployedBytecode.object"]}},"remappings":["nitro-contracts=src/.cache/nitro-contracts/main/src","solady=src/.cache/solady/main/src"],"viaIR":true},"version":"0.8.30+commit.73712a01"}],"contractTypes":{"ArbitrumOneAdminUpdateStrategy":{"abi":[{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InsufficientMsgValue","type":"error"},{"inputs":[],"name":"INBOX","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address[]","name":"newAdministrators","type":"address[]"},{"internalType":"uint256","name":"newWithdrawalQuorum","type":"uint256"}],"name":"setAdministrators","outputs":[],"stateMutability":"payable","type":"function"}],"contractName":"ArbitrumOneAdminUpdateStrategy","deploymentBytecode":{"bytecode":"0x608080604052346015576102a4908161001a8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c8063075034ae146100615763b70106971461002f575f80fd5b3461005d575f36600319011261005d576020604051734dbd4fc535ac27206064b68ffcf827b0a60bab3f8152f35b5f80fd5b606036600319011261005d576004356001600160a01b0381169081900361005d5760243567ffffffffffffffff811161005d573660238201121561005d5780600401359167ffffffffffffffff831161005d573660248460051b8401011161005d57667c585087238000341061021a576040519160208301936323c5673160e01b8552806064850160406024870152526024608485019201905f905b8082106101f0578660208761012488610127838a604435604483015203601f198101855284610238565b604051948593849263679b6ded60e01b845260048401525f602484015266470de4df8200006044840152336064840152336084840152622dc6c060a484015264012a05f20060c484015261010060e4840152518091816101048501528484015e5f828201840152601f01601f1916810103018134734dbd4fc535ac27206064b68ffcf827b0a60bab3f5af180156101e5576101be57005b602090813d83116101de575b6101d48183610238565b8101031261005d57005b503d6101ca565b6040513d5f823e3d90fd5b90919283359060018060a01b03821680920361005d576020816001938293520194019201906100fd565b631f2dda7760e21b5f5234600452667c58508723800060245260445ffd5b90601f8019910116810190811067ffffffffffffffff82111761025a57604052565b634e487b7160e01b5f52604160045260245ffdfea2646970667358221220ebaa77dd092a054679c080b6c72489a0f6279939ed0d7fdc0f0c1b834c8a133564736f6c634300081e0033"},"devdoc":{"kind":"dev","methods":{"setAdministrators(address,address[],uint256)":{"details":"This function forwards a cross-chain call to the target `vault` using Arbitrum's retryable ticket mechanism. The credential manager must supply sufficient `msg.value` to cover the maximum submission cost and gas fees for execution on the destination chain.Reverts with {InsufficientMsgValue} if `msg.value` is less than `MAX_SUBMISSION_COST + GAS_LIMIT * MAX_FEE_PER_GAS`.","params":{"newAdministrators":"The complete list of administrator addresses to set on the vault.","newWithdrawalQuorum":"The new quorum required for withdrawals.","vault":"The address of the vault contract whose administrators will be updated."}}},"version":1},"methodIdentifiers":{"INBOX()":"0xb7010697","setAdministrators(address,address[],uint256)":"0x075034ae"},"runtimeBytecode":{"bytecode":"0x60806040526004361015610011575f80fd5b5f3560e01c8063075034ae146100615763b70106971461002f575f80fd5b3461005d575f36600319011261005d576020604051734dbd4fc535ac27206064b68ffcf827b0a60bab3f8152f35b5f80fd5b606036600319011261005d576004356001600160a01b0381169081900361005d5760243567ffffffffffffffff811161005d573660238201121561005d5780600401359167ffffffffffffffff831161005d573660248460051b8401011161005d57667c585087238000341061021a576040519160208301936323c5673160e01b8552806064850160406024870152526024608485019201905f905b8082106101f0578660208761012488610127838a604435604483015203601f198101855284610238565b604051948593849263679b6ded60e01b845260048401525f602484015266470de4df8200006044840152336064840152336084840152622dc6c060a484015264012a05f20060c484015261010060e4840152518091816101048501528484015e5f828201840152601f01601f1916810103018134734dbd4fc535ac27206064b68ffcf827b0a60bab3f5af180156101e5576101be57005b602090813d83116101de575b6101d48183610238565b8101031261005d57005b503d6101ca565b6040513d5f823e3d90fd5b90919283359060018060a01b03821680920361005d576020816001938293520194019201906100fd565b631f2dda7760e21b5f5234600452667c58508723800060245260445ffd5b90601f8019910116810190811067ffffffffffffffff82111761025a57604052565b634e487b7160e01b5f52604160045260245ffdfea2646970667358221220ebaa77dd092a054679c080b6c72489a0f6279939ed0d7fdc0f0c1b834c8a133564736f6c634300081e0033"},"sourceId":"src/strategies/ArbitrumOneAdminUpdateStrategy.sol","sourcemap":"257:2167:24:-:0;;;;;;;;;;;;;;;;;","userdoc":{"errors":{"InsufficientMsgValue(uint256,uint256)":[{"notice":"Reverts if not enough value was sent to the update method."}]},"kind":"user","methods":{"setAdministrators(address,address[],uint256)":{"notice":"Updates the administrator set and withdrawal quorum on a vault via a retryable ticket."}},"version":1}},"Checkpointer":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadySet","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotCouncilMultisig","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string[]","name":"approvedWithdrawals","type":"string[]"}],"name":"Withdrawals","type":"event"},{"inputs":[],"name":"CHECKPOINT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"sharedSignature","type":"bytes"},{"internalType":"bytes","name":"leaderSignature","type":"bytes"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint8[]","name":"stateRoot","type":"uint8[]"},{"internalType":"string[]","name":"approvedWithdrawals","type":"string[]"}],"internalType":"struct Checkpointer.Checkpoint","name":"_checkpoint","type":"tuple"}],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"councilMultisig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"leader","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"}],"name":"setDomainSeparator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCouncilMultisig","type":"address"}],"name":"setInitialCouncilMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newLeader","type":"address"}],"name":"setLeader","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCouncilMultisig","type":"address"}],"name":"setNewCouncilMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stateRoot","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stateRootNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"contractName":"Checkpointer","deploymentBytecode":{"bytecode":"0x608080604052346026575f80546001600160a01b03191633179055610b3e908161002b8239f35b5f80fdfe6080806040526004361015610012575f80fd5b5f3560e01c90816307ddaf53146108be575080633ea987d31461086657806340eedabb1461083e5780634331e8dd146107ea5780635fa993b214610792578063704b6c02146107455780637438b937146106f657806374ebc7a0146106d95780638bbb26a314610150578063cc2fc84514610105578063e1193e4c146100cb5763f851a440146100a0575f80fd5b346100c7575f3660031901126100c7575f546040516001600160a01b039091168152602090f35b5f80fd5b346100c7575f3660031901126100c75760206040517ff0231fa1a05c1ebcb4f35a12b1dcea172e840b8488bfdf9a22a26a8c427f94d88152f35b346100c75760203660031901126100c7576004356005548110156100c75760209060055f5260ff8160051c5f516020610ae95f395f51905f52015460f86040519360031b161c168152f35b346100c75760603660031901126100c75760043567ffffffffffffffff81116100c7576101819036906004016108e1565b60243567ffffffffffffffff81116100c7576101a19036906004016108e1565b906044359267ffffffffffffffff84116100c7578360040191606060031986360301126100c757823593600354918286036100c75760248701916101e5838761090f565b906040519060208201928391905f905b8082106106b45750505090610216816044949303601f198101835282610945565b519020980194610226868861090f565b610232819c929c610967565b9b6102406040519d8e610945565b818d5260208d019160051b8101903682116100c75780925b82841061067757505050508a51986102886102728b610967565b9a6102806040519c8d610945565b808c52610967565b60208b019b90601f1901368d375f5b8d518110156102c857808c8f826102b36001956102c1936109d3565b5160208151910120926109d3565b5201610297565b506040518b5160208201919082908f905f5b81811061066157505050918161030361039f97959361039999979503601f198101835282610945565b5190206040519160208301937ff0231fa1a05c1ebcb4f35a12b1dcea172e840b8488bfdf9a22a26a8c427f94d885526040840152606083015260808201526080815261035060a082610945565b5190206004549060405190602082019261190160f01b84526022830152604282015260428152610381606282610945565b51902093849160018060a01b035f541693369161097f565b916109fb565b15610652576103996103be9360018060a01b036001541693369161097f565b15610652575f19821461063e5760016103db92016003558361090f565b929067ffffffffffffffff841161062a5768010000000000000000841161062a57600554846005558085106105a0575b509260055f528060051c5f5b81811061055e5750601f1982169091039081610500575b505061043a925061090f565b906040519082602083016020845252604082019060408460051b84010193815f90601e19813603015b838310610492577fef889901cd5d865c829bdf171647f02f76efbce3c0cba77197094981f41a727c87890388a1005b909192939496603f198782030188528535828112156100c7578301906020823592019167ffffffffffffffff81116100c75780360383136100c7576020828280600196849695859652848401375f828201840152601f01601f19160101999190910196019493019190610463565b5f9485925b80871061052a57505061043a94505f516020610ae95f395f51905f520155838061042e565b909260206105536001928961053e886109c5565b919060ff809160031b9316831b921b19161790565b940196019590610505565b5f5f5b6020811061058357505f516020610ae95f395f51905f52820155600101610417565b969060206105976001928a61053e866109c5565b92019701610561565b601f80860160051c910160051c5f516020610ae95f395f51905f520190601f8616806105f0575b505f516020610ae95f395f51905f52015b8181106105e5575061040b565b5f81556001016105d8565b7f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3daf8201908154905f199060200360031b1c169055866105c7565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b638baa579f60e01b5f5260045ffd5b82518452602093840193909201916001016102da565b833567ffffffffffffffff81116100c757820136601f820112156100c7576020916106a983923690848135910161097f565b815201930192610258565b90919283359060ff82168092036100c7576020816001938293520194019201906101f5565b346100c7575f3660031901126100c7576020600354604051908152f35b346100c75760203660031901126100c7575f546001600160a01b031633036107365760045461072757600480359055005b63a741a04560e01b5f5260045ffd5b637bfa4b9f60e01b5f5260045ffd5b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7575f546001600160a01b03811633036107365781156100c7576001600160a01b031916175f55005b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7576002546001600160a01b03811633036107db576001600160a01b03191617600255005b638d62b6d960e01b5f5260045ffd5b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7576002546001600160a01b031633036107db576bffffffffffffffffffffffff60a01b60015416176001555f80f35b346100c7575f3660031901126100c7576001546040516001600160a01b039091168152602090f35b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7575f546001600160a01b03163303610736576002546001600160a01b038116610727576001600160a01b03191617600255005b346100c7575f3660031901126100c7576002546001600160a01b03168152602090f35b9181601f840112156100c75782359167ffffffffffffffff83116100c757602083818601950101116100c757565b903590601e19813603018212156100c7570180359067ffffffffffffffff82116100c757602001918160051b360383136100c757565b90601f8019910116810190811067ffffffffffffffff82111761062a57604052565b67ffffffffffffffff811161062a5760051b60200190565b92919267ffffffffffffffff821161062a57604051916109a9601f8201601f191660200184610945565b8294818452818301116100c7578281602093845f960137010152565b3560ff811681036100c75790565b80518210156109e75760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b90915f91906001600160a01b03821615610ae05760405192600484019460248501956044860192853b15610a6457509186939160209593630b135d3f60e11b8852526040845281518501809260045afa9360443d01915afa9151630b135d3f60e11b1491161690565b979650509050815180604014610abb57604114610a815750505050565b60209293955060608201515f1a835260408201516060525b5f5201516040526020600160805f825afa511860601b3d11915f606052604052565b506020929395506040820151601b8160ff1c01845260018060ff1b0316606052610a99565b505050505f9056fe036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0a2646970667358221220f9ddb3830cc5bf0b146ee5d4475497fa0dfd801400dfcae202dc378109e06fb664736f6c634300081e0033"},"devdoc":{"details":"Designed for use in DStack-like distributed settlement systems.","events":{"Withdrawals(string[])":{"params":{"approvedWithdrawals":"List of withdrawal IDs approved in the checkpoint."}}},"kind":"dev","methods":{"checkpoint(bytes,bytes,(uint256,uint8[],string[]))":{"details":"Requires valid EIP-712 signatures from both admin and leader.","params":{"_checkpoint":"The checkpoint payload to commit.","leaderSignature":"Signature by the leader.","sharedSignature":"Signature by the admin."}},"constructor":{"details":"Sets the deployer as the initial admin."},"setAdmin(address)":{"params":{"newAdmin":"The new admin address."}},"setDomainSeparator(bytes32)":{"params":{"domainSeparator":"The domain separator to store."}},"setInitialCouncilMultisig(address)":{"params":{"newCouncilMultisig":"The council's Gnosis Safe address."}},"setLeader(address)":{"details":"This should be reviewed depending on the leader rotation mechanism.","params":{"newLeader":"The address of the new leader node."}},"setNewCouncilMultisig(address)":{"params":{"newCouncilMultisig":"The new multisig address."}}},"stateVariables":{"admin":{"details":"Should be set to the DStack app shared secret public key."},"councilMultisig":{"details":"Can rotate the leader and self."},"leader":{"details":"Leader is responsible for signing and submitting new checkpoints."},"stateRoot":{"details":"Serialized as `(user, eth_balance, usdc_balance, deposit_nonce, is_mm)` tuples. In production, this may store multiple roots and rotate."},"stateRootNonce":{"details":"Used to prevent replay attacks and enforce checkpoint ordering."}},"title":"Checkpointer","version":1},"methodIdentifiers":{"CHECKPOINT_TYPEHASH()":"0xe1193e4c","admin()":"0xf851a440","checkpoint(bytes,bytes,(uint256,uint8[],string[]))":"0x8bbb26a3","councilMultisig()":"0x07ddaf53","leader()":"0x40eedabb","setAdmin(address)":"0x704b6c02","setDomainSeparator(bytes32)":"0x7438b937","setInitialCouncilMultisig(address)":"0x3ea987d3","setLeader(address)":"0x4331e8dd","setNewCouncilMultisig(address)":"0x5fa993b2","stateRoot(uint256)":"0xcc2fc845","stateRootNonce()":"0x74ebc7a0"},"runtimeBytecode":{"bytecode":"0x6080806040526004361015610012575f80fd5b5f3560e01c90816307ddaf53146108be575080633ea987d31461086657806340eedabb1461083e5780634331e8dd146107ea5780635fa993b214610792578063704b6c02146107455780637438b937146106f657806374ebc7a0146106d95780638bbb26a314610150578063cc2fc84514610105578063e1193e4c146100cb5763f851a440146100a0575f80fd5b346100c7575f3660031901126100c7575f546040516001600160a01b039091168152602090f35b5f80fd5b346100c7575f3660031901126100c75760206040517ff0231fa1a05c1ebcb4f35a12b1dcea172e840b8488bfdf9a22a26a8c427f94d88152f35b346100c75760203660031901126100c7576004356005548110156100c75760209060055f5260ff8160051c5f516020610ae95f395f51905f52015460f86040519360031b161c168152f35b346100c75760603660031901126100c75760043567ffffffffffffffff81116100c7576101819036906004016108e1565b60243567ffffffffffffffff81116100c7576101a19036906004016108e1565b906044359267ffffffffffffffff84116100c7578360040191606060031986360301126100c757823593600354918286036100c75760248701916101e5838761090f565b906040519060208201928391905f905b8082106106b45750505090610216816044949303601f198101835282610945565b519020980194610226868861090f565b610232819c929c610967565b9b6102406040519d8e610945565b818d5260208d019160051b8101903682116100c75780925b82841061067757505050508a51986102886102728b610967565b9a6102806040519c8d610945565b808c52610967565b60208b019b90601f1901368d375f5b8d518110156102c857808c8f826102b36001956102c1936109d3565b5160208151910120926109d3565b5201610297565b506040518b5160208201919082908f905f5b81811061066157505050918161030361039f97959361039999979503601f198101835282610945565b5190206040519160208301937ff0231fa1a05c1ebcb4f35a12b1dcea172e840b8488bfdf9a22a26a8c427f94d885526040840152606083015260808201526080815261035060a082610945565b5190206004549060405190602082019261190160f01b84526022830152604282015260428152610381606282610945565b51902093849160018060a01b035f541693369161097f565b916109fb565b15610652576103996103be9360018060a01b036001541693369161097f565b15610652575f19821461063e5760016103db92016003558361090f565b929067ffffffffffffffff841161062a5768010000000000000000841161062a57600554846005558085106105a0575b509260055f528060051c5f5b81811061055e5750601f1982169091039081610500575b505061043a925061090f565b906040519082602083016020845252604082019060408460051b84010193815f90601e19813603015b838310610492577fef889901cd5d865c829bdf171647f02f76efbce3c0cba77197094981f41a727c87890388a1005b909192939496603f198782030188528535828112156100c7578301906020823592019167ffffffffffffffff81116100c75780360383136100c7576020828280600196849695859652848401375f828201840152601f01601f19160101999190910196019493019190610463565b5f9485925b80871061052a57505061043a94505f516020610ae95f395f51905f520155838061042e565b909260206105536001928961053e886109c5565b919060ff809160031b9316831b921b19161790565b940196019590610505565b5f5f5b6020811061058357505f516020610ae95f395f51905f52820155600101610417565b969060206105976001928a61053e866109c5565b92019701610561565b601f80860160051c910160051c5f516020610ae95f395f51905f520190601f8616806105f0575b505f516020610ae95f395f51905f52015b8181106105e5575061040b565b5f81556001016105d8565b7f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3daf8201908154905f199060200360031b1c169055866105c7565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b638baa579f60e01b5f5260045ffd5b82518452602093840193909201916001016102da565b833567ffffffffffffffff81116100c757820136601f820112156100c7576020916106a983923690848135910161097f565b815201930192610258565b90919283359060ff82168092036100c7576020816001938293520194019201906101f5565b346100c7575f3660031901126100c7576020600354604051908152f35b346100c75760203660031901126100c7575f546001600160a01b031633036107365760045461072757600480359055005b63a741a04560e01b5f5260045ffd5b637bfa4b9f60e01b5f5260045ffd5b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7575f546001600160a01b03811633036107365781156100c7576001600160a01b031916175f55005b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7576002546001600160a01b03811633036107db576001600160a01b03191617600255005b638d62b6d960e01b5f5260045ffd5b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7576002546001600160a01b031633036107db576bffffffffffffffffffffffff60a01b60015416176001555f80f35b346100c7575f3660031901126100c7576001546040516001600160a01b039091168152602090f35b346100c75760203660031901126100c7576004356001600160a01b038116908190036100c7575f546001600160a01b03163303610736576002546001600160a01b038116610727576001600160a01b03191617600255005b346100c7575f3660031901126100c7576002546001600160a01b03168152602090f35b9181601f840112156100c75782359167ffffffffffffffff83116100c757602083818601950101116100c757565b903590601e19813603018212156100c7570180359067ffffffffffffffff82116100c757602001918160051b360383136100c757565b90601f8019910116810190811067ffffffffffffffff82111761062a57604052565b67ffffffffffffffff811161062a5760051b60200190565b92919267ffffffffffffffff821161062a57604051916109a9601f8201601f191660200184610945565b8294818452818301116100c7578281602093845f960137010152565b3560ff811681036100c75790565b80518210156109e75760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b90915f91906001600160a01b03821615610ae05760405192600484019460248501956044860192853b15610a6457509186939160209593630b135d3f60e11b8852526040845281518501809260045afa9360443d01915afa9151630b135d3f60e11b1491161690565b979650509050815180604014610abb57604114610a815750505050565b60209293955060608201515f1a835260408201516060525b5f5201516040526020600160805f825afa511860601b3d11915f606052604052565b506020929395506040820151601b8160ff1c01845260018060ff1b0316606052610a99565b505050505f9056fe036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0a2646970667358221220f9ddb3830cc5bf0b146ee5d4475497fa0dfd801400dfcae202dc378109e06fb664736f6c634300081e0033"},"sourceId":"src/Checkpointer.sol","sourcemap":"413:6397:13:-:0;;;;;;;2546:18;413:6397;;-1:-1:-1;;;;;;413:6397:13;2554:10;413:6397;;;;;;;;;;;;;","userdoc":{"errors":{"AlreadySet()":[{"notice":"Reverts if a value has already been set."}],"InvalidSignature()":[{"notice":"Reverts if a signature does not match the expected signer or payload."}],"NotAdmin()":[{"notice":"Reverts if caller is not the admin."}],"NotCouncilMultisig()":[{"notice":"Reverts if caller is not the current council multisig."}]},"events":{"Withdrawals(string[])":{"notice":"Emitted when a new list of approved withdrawals is recorded in a checkpoint."}},"kind":"user","methods":{"CHECKPOINT_TYPEHASH()":{"notice":"Typehash used for EIP-712 encoding of the Checkpoint struct."},"admin()":{"notice":"Address with the authority to set initial parameters."},"checkpoint(bytes,bytes,(uint256,uint8[],string[]))":{"notice":"Checkpoint submitted by a node to update the system state."},"constructor":{"notice":"Contract constructor."},"councilMultisig()":{"notice":"Gnosis Safe address used as the council multisig."},"leader()":{"notice":"Public key of the current designated leader node."},"setAdmin(address)":{"notice":"Transfers admin control to a new address."},"setDomainSeparator(bytes32)":{"notice":"Sets the EIP-712 domain separator used for verifying signatures."},"setInitialCouncilMultisig(address)":{"notice":"Sets the initial council multisig address."},"setLeader(address)":{"notice":"Sets the leader node address."},"setNewCouncilMultisig(address)":{"notice":"Allows the current council to rotate itself to a new address."},"stateRoot(uint256)":{"notice":"The current state root, encoded as a serialized vector."},"stateRootNonce()":{"notice":"Monotonically increasing nonce for checkpoint submissions."}},"notice":"Tracks and validates state root checkpoints using EIP-712 signatures from admin and leader nodes.","version":1}},"CredentialManager":{"abi":[{"inputs":[{"internalType":"address[]","name":"initialOperators","type":"address[]"},{"internalType":"uint256","name":"initialQuorumThreshold","type":"uint256"},{"internalType":"address","name":"initialRiskManager","type":"address"},{"internalType":"address","name":"initialRegistryContract","type":"address"},{"components":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"bytes32","name":"mrtd","type":"bytes32"},{"internalType":"bytes32","name":"rtmr0","type":"bytes32"},{"internalType":"bytes32","name":"rtmr1","type":"bytes32"},{"internalType":"bytes32","name":"rtmr2","type":"bytes32"},{"internalType":"bytes32","name":"rtmr3","type":"bytes32"}],"internalType":"struct CredentialManager.MeasurementProfile[]","name":"initialMeasurements","type":"tuple[]"},{"internalType":"address","name":"initialAutomataVerifier","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AmbiguousState","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"GatheringActive","type":"error"},{"inputs":[],"name":"GatheringNotActive","type":"error"},{"inputs":[],"name":"GatheringNotExpired","type":"error"},{"inputs":[{"internalType":"uint256","name":"provided","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"InsufficientSignatures","type":"error"},{"inputs":[{"internalType":"uint256","name":"delay","type":"uint256"}],"name":"InvalidDelay","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"InvalidEpoch","type":"error"},{"inputs":[],"name":"InvalidProfileConfig","type":"error"},{"inputs":[],"name":"InvalidProfileId","type":"error"},{"inputs":[{"internalType":"uint256","name":"newQuorum","type":"uint256"},{"internalType":"uint256","name":"operatorCount","type":"uint256"}],"name":"InvalidQuorum","type":"error"},{"inputs":[],"name":"InvalidQuoteLength","type":"error"},{"inputs":[],"name":"InvalidReportData","type":"error"},{"inputs":[],"name":"InvalidVaultAddr","type":"error"},{"inputs":[],"name":"InvalidVerifier","type":"error"},{"inputs":[],"name":"InvalidZkProof","type":"error"},{"inputs":[{"internalType":"bytes32","name":"expected","type":"bytes32"},{"internalType":"bytes32","name":"actual","type":"bytes32"},{"internalType":"string","name":"field","type":"string"}],"name":"MeasurementMismatch","type":"error"},{"inputs":[],"name":"NoCandidate","type":"error"},{"inputs":[],"name":"NoStrategy","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"NotOperator","type":"error"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"}],"name":"ProfileInactive","type":"error"},{"inputs":[{"internalType":"uint256","name":"current","type":"uint256"},{"internalType":"uint256","name":"proposed","type":"uint256"}],"name":"ProposedEpochTooLow","type":"error"},{"inputs":[],"name":"SignersNotSortedOrUnique","type":"error"},{"inputs":[],"name":"StrategyAlreadyExists","type":"error"},{"inputs":[{"internalType":"bytes32","name":"opId","type":"bytes32"}],"name":"TimelockAlreadyCanceled","type":"error"},{"inputs":[{"internalType":"bytes32","name":"opId","type":"bytes32"}],"name":"TimelockAlreadyExecuted","type":"error"},{"inputs":[{"internalType":"bytes32","name":"opId","type":"bytes32"},{"internalType":"uint256","name":"readyAt","type":"uint256"},{"internalType":"uint256","name":"nowTs","type":"uint256"}],"name":"TimelockNotReady","type":"error"},{"inputs":[{"internalType":"bytes32","name":"opId","type":"bytes32"}],"name":"TimelockUnknown","type":"error"},{"inputs":[{"internalType":"uint256","name":"routingId","type":"uint256"},{"internalType":"uint256","name":"vmId","type":"uint256"}],"name":"VaultNotFound","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"routingId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vmId","type":"uint256"},{"indexed":false,"internalType":"address","name":"strategy","type":"address"}],"name":"AdminUpdateStrategyRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"bytes32","name":"newAttestedKey","type":"bytes32"}],"name":"AttestedKeyRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldVerifier","type":"address"},{"indexed":true,"internalType":"address","name":"newVerifier","type":"address"}],"name":"AutomataVerifierUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"routingId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vmId","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"newAdministrators","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"newWithdrawalQuorum","type":"uint256"}],"name":"DepositVaultAdministratorsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"newAdministrators","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"newWithdrawalQuorum","type":"uint256"}],"name":"DepositVaultAdministratorsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newEpoch","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"newCheckpointHash","type":"bytes32"}],"name":"EpochIncremented","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newLeader","type":"address"},{"indexed":true,"internalType":"bytes32","name":"newAttestedKey","type":"bytes32"}],"name":"LeaderUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"MeasurementProfileUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"newMrtd","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"newRtmr0","type":"bytes32"}],"name":"MeasurementsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"opId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"opType","type":"bytes32"}],"name":"OperationCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"opId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"opType","type":"bytes32"}],"name":"OperationExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"opId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"opType","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"eta","type":"uint256"}],"name":"OperationScheduled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"}],"name":"OperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldThreshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newThreshold","type":"uint256"}],"name":"QuorumThresholdUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldRegistry","type":"address"},{"indexed":true,"internalType":"address","name":"newRegistry","type":"address"}],"name":"RegistryUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"hash1","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"hash2","type":"bytes32"}],"name":"RestartAmbiguityDetected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"leader","type":"address"},{"indexed":false,"internalType":"uint256","name":"epoch","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"checkpointHash","type":"bytes32"}],"name":"RestartCandidateSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newLeader","type":"address"},{"indexed":true,"internalType":"uint256","name":"epoch","type":"uint256"}],"name":"RestartExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"RestartGatheringStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldRiskManager","type":"address"},{"indexed":true,"internalType":"address","name":"newRiskManager","type":"address"}],"name":"RiskManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"targetOpType","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"oldDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDelay","type":"uint256"}],"name":"TimelockDelayUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"routingId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vmId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"vaultAddr","type":"bytes32"},{"components":[{"internalType":"uint64","name":"blockTimeMs","type":"uint64"},{"internalType":"uint8","name":"defaultConfirmations","type":"uint8"},{"internalType":"uint8","name":"depositIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"withdrawalIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"settlementIngestConfirmations","type":"uint8"}],"indexed":false,"internalType":"struct CredentialManager.ChainConfig","name":"config","type":"tuple"}],"name":"VaultAdded","type":"event"},{"inputs":[],"name":"GATHERING_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_ADD_VAULT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_APPOINT_LEADER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_CANCEL_TIMELOCK","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_MANAGE_PROFILE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_REGISTER_STRATEGY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_RESTART","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_SET_AUTOMATA_VERIFIER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_SET_DELAY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_SET_MEASUREMENTS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_SET_QUORUM","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_SET_REGISTRY","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_SET_RISK_MANAGER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_SET_VAULT_ADMINS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OP_WITHDRAW","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"routingId","type":"uint8"},{"internalType":"uint256","name":"vmId","type":"uint256"},{"internalType":"bytes32","name":"vaultAddr","type":"bytes32"},{"components":[{"internalType":"uint64","name":"blockTimeMs","type":"uint64"},{"internalType":"uint8","name":"defaultConfirmations","type":"uint8"},{"internalType":"uint8","name":"depositIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"withdrawalIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"settlementIngestConfirmations","type":"uint8"}],"internalType":"struct CredentialManager.ChainConfig","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"addVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"adminUpdateStrategies","outputs":[{"internalType":"contract IAdminUpdateStrategy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newLeader","type":"address"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"appointLeader","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"automataVerifier","outputs":[{"internalType":"contract IAutomataDcapAttestation","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bestCandidate","outputs":[{"internalType":"address","name":"leader","type":"address"},{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"bytes32","name":"checkpointHash","type":"bytes32"},{"internalType":"bool","name":"exists","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"opId","type":"bytes32"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"cancelTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"components":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"bytes32","name":"mrtd","type":"bytes32"},{"internalType":"bytes32","name":"rtmr0","type":"bytes32"},{"internalType":"bytes32","name":"rtmr1","type":"bytes32"},{"internalType":"bytes32","name":"rtmr2","type":"bytes32"},{"internalType":"bytes32","name":"rtmr3","type":"bytes32"}],"internalType":"struct CredentialManager.MeasurementProfile","name":"profile","type":"tuple"}],"name":"executeManageProfile","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRegistry","type":"address"}],"name":"executeRegistryContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRiskManager","type":"address"}],"name":"executeRiskManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newVerifier","type":"address"}],"name":"executeUpdateAutomataVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCouncilConfig","outputs":[{"internalType":"address[]","name":"members","type":"address[]"},{"internalType":"uint256","name":"k","type":"uint256"},{"internalType":"uint256","name":"n","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLeader","outputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes32","name":"attestedKey","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"start","type":"uint16"},{"internalType":"uint16","name":"end","type":"uint16"}],"name":"getVaults","outputs":[{"components":[{"internalType":"uint8","name":"routingId","type":"uint8"},{"internalType":"uint256","name":"vmId","type":"uint256"},{"internalType":"bytes32","name":"vaultAddress","type":"bytes32"},{"components":[{"internalType":"uint64","name":"blockTimeMs","type":"uint64"},{"internalType":"uint8","name":"defaultConfirmations","type":"uint8"},{"internalType":"uint8","name":"depositIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"withdrawalIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"settlementIngestConfirmations","type":"uint8"}],"internalType":"struct CredentialManager.ChainConfig","name":"config","type":"tuple"}],"internalType":"struct CredentialManager.Vault[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initiateRestart","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRestartAmbiguous","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestCheckpointHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"leader","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"measurementProfiles","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"bytes32","name":"mrtd","type":"bytes32"},{"internalType":"bytes32","name":"rtmr0","type":"bytes32"},{"internalType":"bytes32","name":"rtmr1","type":"bytes32"},{"internalType":"bytes32","name":"rtmr2","type":"bytes32"},{"internalType":"bytes32","name":"rtmr3","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextProfileId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"operatorToAttestedKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"operators","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorumThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"routingId","type":"uint8"},{"internalType":"uint256","name":"vmId","type":"uint256"},{"internalType":"contract IAdminUpdateStrategy","name":"strategy","type":"address"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"registerAdminUpdateStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newAttestedKey","type":"bytes32"}],"name":"registerAttestedKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"registryContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"resolveRestart","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"restartGatheringDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"riskManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"components":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"bytes32","name":"mrtd","type":"bytes32"},{"internalType":"bytes32","name":"rtmr0","type":"bytes32"},{"internalType":"bytes32","name":"rtmr1","type":"bytes32"},{"internalType":"bytes32","name":"rtmr2","type":"bytes32"},{"internalType":"bytes32","name":"rtmr3","type":"bytes32"}],"internalType":"struct CredentialManager.MeasurementProfile","name":"profile","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"scheduleManageProfile","outputs":[{"internalType":"bytes32","name":"opId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRegistry","type":"address"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"scheduleRegistryContract","outputs":[{"internalType":"bytes32","name":"opId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRiskManager","type":"address"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"scheduleRiskManager","outputs":[{"internalType":"bytes32","name":"opId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newVerifier","type":"address"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"scheduleUpdateAutomataVerifier","outputs":[{"internalType":"bytes32","name":"opId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"routingId","type":"uint256"},{"internalType":"uint256","name":"vmId","type":"uint256"},{"internalType":"address[]","name":"newAdministrators","type":"address[]"},{"internalType":"uint256","name":"newWithdrawalQuorum","type":"uint256"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"setDepositVaultAdministrators","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"bytes","name":"tdxReportBody","type":"bytes"},{"internalType":"bytes","name":"zkProof","type":"bytes"},{"internalType":"address","name":"newLeader","type":"address"},{"internalType":"bytes32","name":"checkpointHash","type":"bytes32"}],"name":"submitRestartProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"timelockDelayFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"timelockOps","outputs":[{"internalType":"uint64","name":"eta","type":"uint64"},{"internalType":"bool","name":"executed","type":"bool"},{"internalType":"bool","name":"canceled","type":"bool"},{"internalType":"bytes32","name":"opType","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newThreshold","type":"uint256"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"updateQuorumThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vaults","outputs":[{"internalType":"uint8","name":"routingId","type":"uint8"},{"internalType":"uint256","name":"vmId","type":"uint256"},{"internalType":"bytes32","name":"vaultAddress","type":"bytes32"},{"components":[{"internalType":"uint64","name":"blockTimeMs","type":"uint64"},{"internalType":"uint8","name":"defaultConfirmations","type":"uint8"},{"internalType":"uint8","name":"depositIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"withdrawalIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"settlementIngestConfirmations","type":"uint8"}],"internalType":"struct CredentialManager.ChainConfig","name":"config","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}],"contractName":"CredentialManager","deploymentBytecode":{"bytecode":"0x6080604052346105515761485d803803806100198161056d565b92833981019060c0818303126105515780516001600160401b0381116105515781019082601f830112156105515781519161005b61005684610592565b61056d565b9260208085838152019160051b8301019185831161055157602001905b828210610555575050506020810151610093604083016105a9565b926100a0606084016105a9565b60808401519093906001600160401b03811161055157810186601f82011215610551578051906100d261005683610592565b97602060c0818b8681520194028301019181831161055157602001925b8284106104db575050505060a061010691016105a9565b6001600e555f80546001600160a01b03191633179055936001600160a01b0316928315610495576001600160a01b031693841561049557601180546001600160a01b0319166001600160a01b039290921691909117905580519081156104c457821580156104bb575b6104a4575f5b82811061038f575050506040817fc33728fb6bc64ec1c5596c946e1406ccdfb7369404098c1d6a5f4a7a29c97b63926003558151905f82526020820152a160018060a01b0319600954161760095560018060a01b0319600a541617600a556001600e555f5b81518110156102c2576101ed81836105bd565b519081511515806102b6575b6102a757602091600e545f52600d835260405f20600560a0835115159360ff1984541660ff861617845586810151600185015560408101516002850155606081015160038501556080810151600485015501519101557faa1bacadd202709f2df9c31faf4babdbb21a245021c22298bfcdf22861ca12c6600e54938492604051908152a25f198214610293576001809201600e55016101da565b634e487b7160e01b5f52601160045260245ffd5b637262f58f60e01b5f5260045ffd5b506020820151156101f9565b600b6020526202a3007ffc320c8b7cd913048d0600d8f8fbdd9fd65e3dee2c1f3796e3abba8cc47fa047556203f4807f5248b41ce7bdc12ebe0248f44130be972d690f78fe7dbe1a76d984641d9dcfc25562093a807f9b6d9405e2a268edd94615fe7f07c0d5d9dda2152c2e48f4e74379972af1c6188190557fa24d58aaa8deed8b2ff0e63d867e6fe155de046522ed61849f5647e59d04b6ba5f527f8de415b97204654c888cc41215aeac0a76fba4f899a3e239bdee8aedbbab23ef5560405161428b90816105d28239f35b6001600160a01b036103a182846105bd565b511690811561049557815f52600260205260ff60405f20541661048657815f52600260205260405f20600160ff19825416179055600154916801000000000000000083101561047257600183018060015583101561045e5760015f8181527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf690940180546001600160a01b03191683179055927fac6fa858e9350a46cec16539926e0fde25b7629f84b5a72bffaae4df888ae86d9080a201610175565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b630da1c57360e41b5f5260045ffd5b63d92e233d60e01b5f5260045ffd5b509063158589c560e11b5f5260045260245260445ffd5b5081831161016f565b8263158589c560e11b5f526004525f60245260445ffd5b60c084830312610551576040519060c082016001600160401b03811183821017610472576040528451908115158203610551578260209260c09452828701518382015260408701516040820152606087015160608201526080870151608082015260a087015160a08201528152019301926100ef565b5f80fd5b60208091610562846105a9565b815201910190610078565b6040519190601f01601f191682016001600160401b0381118382101761047257604052565b6001600160401b0381116104725760051b60200190565b51906001600160a01b038216820361055157565b805182101561045e5760209160051b01019056fe6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c806304235842146103c95780631276bcc5146103c4578063127f49ad146103bf5780631ac4d079146103ba5780631bc12e07146103b557806324242e77146103b057806326ddc1ba146103ab5780632808e92f146103a6578063280cd09d146103a1578063281cbdd41461039c57806328c1f99b146103975780632d4ab28d14610392578063317095201461038d5780633174b72714610388578063333bef221461038357806335cfd9eb1461037e57806340eedabb14610379578063413721f614610374578063478426631461036f5780634c051f141461036a5780634e970c8c146103655780635cc79144146103605780635d3ae3901461035b5780635f250f69146103565780636583c37a14610351578063669f6f351461034c5780636d70f7ae146103475780636dfb32aa146103425780637b7a91dd1461033d5780637f0152a81461033857806381392328146103335780638c64ea4a1461032e5780639005474214610329578063900cf0cf1461032457806395c825591461031f5780639d3e015a1461031a5780639fd7285c14610315578063a6aac51314610310578063acfacc861461030b578063ae5c8bfb14610306578063b34eb18214610301578063b5ed8b12146102fc578063b7635fb8146102f7578063be223838146102f2578063c7d06b54146102ed578063cd1d81ff146102e8578063ce0b1302146102e3578063d8a0bebf146102de578063d9be832c146102d9578063dd6fbaa2146102d4578063e0913aff146102cf578063e28d4906146102ca578063f5949cd6146102c5578063f5b68c67146102c0578063f698da25146102bb578063f851a440146102b6578063fb834493146102b1578063fc0e2ba7146102ac5763fdeabe1f0361000e57611ecc565b611e92565b611e68565b611e41565b611e1f565b611df8565b611dbe565b611d64565b611d2a565b611c39565b611c1c565b611be2565b611b73565b611b29565b611a4f565b6119d9565b6119b2565b6118c9565b6118ac565b6117ca565b6116f8565b6116cb565b6115f6565b61149b565b611435565b611418565b6113de565b61133c565b6111a7565b61112e565b611111565b61104e565b61100e565b610fcb565b610f91565b610f57565b610db3565b610d0b565b610cd1565b610c9c565b610c74565b610bef565b610bc7565b610a92565b610a58565b610a18565b6109bf565b610998565b610970565b610887565b61085f565b610706565b61063e565b61056c565b610545565b61050a565b6104dc565b6104ba565b610422565b9093929193606082016060835281518091526020608084019201905f5b81811061040357505050906040919460208201520152565b82516001600160a01b03168452602093840193909201916001016103eb565b346104b6575f3660031901126104b65760035460015460405190602082828152019060015f52827fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65f5b838110610494575050610484906104909303846112be565b604051938493846103ce565b0390f35b81546001600160a01b031685526020909401938592506001918201910161046c565b5f80fd5b346104b6575f3660031901126104b657602060ff601754166040519015158152f35b346104b6575f3660031901126104b6576020601254604051908152f35b6001600160a01b038116036104b657565b346104b65760203660031901126104b657600435610527816104f9565b60018060a01b03165f526005602052602060405f2054604051908152f35b346104b6575f3660031901126104b65760206040515f5160206142365f395f51905f528152f35b346104b65760203660031901126104b657600435610589816104f9565b6001600160a01b03811690811561062f575f5160206142365f395f51905f526105cd6040516020810190858252602081526105c56040826112be565b519020612db7565b6105d681612ec3565b600a80546001600160a01b031981166001600160a01b0395861617909155909216915f5160206141f65f395f51905f525f80a37f482b97c53e48ffa324a976e2738053e9aff6eee04d8aac63b10e19411d869b825f80a3005b63d92e233d60e01b5f5260045ffd5b346104b6575f3660031901126104b65760206040517f3f98d537f24f3ae50e4a30e12fbf3e5c35cf6f40f4ce125c82c1b88e3e7cf3df8152f35b9181601f840112156104b6578235916001600160401b0383116104b6576020808501948460051b0101116104b657565b9060606003198301126104b6576004356106c1816104f9565b916024356001600160401b0381116104b657816106e091600401610678565b92909291604435906001600160401b0382116104b65761070291600401610678565b9091565b346104b657610714366106a8565b91936001600160a01b03169190821561062f57610765946107529360405160208101918252602081526107486040826112be565b5190209485612ff1565b5f5160206141d65f395f51905f52612e97565b805f52600c60205260405f209060ff825460401c1661084d575f5160206141d65f395f51905f525f52600b6020527ffc320c8b7cd913048d0600d8f8fbdd9fd65e3dee2c1f3796e3abba8cc47fa0475491821561083957815f5160206141b65f395f51905f5261082e5f5160206141d65f395f51905f52938460016107fb6107ef60209a426121d5565b6001600160401b031690565b835469ffffffffffffffffffff19166001600160401b039190911690811784559201556040519081529081906020820190565b0390a3604051908152f35b6309913ab360e31b5f52600483905260245ffd5b633599e08d60e21b5f5260045260245ffd5b346104b6575f3660031901126104b6576011546040516001600160a01b039091168152602090f35b346104b657610895366106a8565b91936001600160a01b03169190821561062f576108e6946108d39360405160208101918252602081526108c96040826112be565b519020948561316a565b5f5160206142165f395f51905f52612e97565b805f52600c60205260405f209060ff825460401c1661084d575f5160206142165f395f51905f525f52600b6020527f5585c2bd0ffb4796fa70abc2a0b1f92173aa4b9f7e1b37d256fd2a975c5abcfa5491821561083957815f5160206141b65f395f51905f5261082e5f5160206142165f395f51905f52938460016107fb6107ef60209a426121d5565b346104b6575f3660031901126104b657600a546040516001600160a01b039091168152602090f35b346104b6575f3660031901126104b65760206040515f5160206142165f395f51905f528152f35b346104b65760203660031901126104b6576004355f52600c602052608060405f206001815491015460ff604051926001600160401b0381168452818160401c161515602085015260481c16151560408301526060820152f35b346104b65760403660031901126104b657600435602435905f52600860205260405f20905f52602052602060018060a01b0360405f205416604051908152f35b346104b6575f3660031901126104b65760206040517f921db041069361e63fc63658404e32c96548fc5d6a72e7fe763cb3c8b370e3fd8152f35b346104b6575f3660031901126104b6576012548015610bb857421115610ba957610ac5610ac160165460ff1690565b1590565b610b9a5760175460ff16610b8b57601354610aed906001600160a01b0316613cbd565b613cbd565b610af8601554601055565b610b03601454600f55565b610b0c5f601255565b610b215f6013555f6014555f6015555f601655565b600f546010546040805183815260208101929092527f88cac99f10d8167541407023871a1cc0d797dc75e5b23f3f9f54aaf445f5602c91a16006546001600160a01b03167fd7936f419066f72741af39dde15237d9aed55a0d1d9ab0cb3280569b42c3d8f35f80a3005b6363f5b90b60e11b5f5260045ffd5b63dcd4760160e01b5f5260045ffd5b63285f264160e21b5f5260045ffd5b63cbd2c74d60e01b5f5260045ffd5b346104b6575f3660031901126104b6576006546040516001600160a01b039091168152602090f35b60c03660031901126104b6576004356024356044356001600160401b0381116104b657610c20903690600401610678565b909290606435906084356001600160401b0381116104b657610c46903690600401610678565b92909160a435966001600160401b0388116104b657610c6c610018983690600401610678565b9790966120d0565b346104b6575f3660031901126104b6576009546040516001600160a01b039091168152602090f35b346104b6575f3660031901126104b657604060018060a01b0360065416805f526005602052815f205482519182526020820152f35b346104b6575f3660031901126104b65760206040517f1f9aa1ad5b6acb4043f0654345360b23371878df9b7f4802b13fcb8d3fbb745f8152f35b346104b6575f3660031901126104b6576012544210610d8657610e104201804211610d8157601255610d485f6013555f6014555f6015555f601655565b60ff19601754166017557f3d364c9a6ad0fb8014a11c487ec342f3a0aaf1a55973fc1bb7353ab6824a358f6020601254604051908152a1005b6121c1565b6301fd8f7b60e41b5f5260045ffd5b6004359060ff821682036104b657565b359060ff821682036104b657565b346104b65760a03660031901126104b657610dcc610d95565b60243590604435610ddc816104f9565b6064356001600160401b0381116104b657610dfb903690600401610678565b9190926084356001600160401b0381116104b657610e1d903690600401610678565b6001600160a01b038416959094919390861561062f57610e7b610e6f610e6f610e628b610e558960ff165f52600860205260405f2090565b905f5260205260405f2090565b546001600160a01b031690565b6001600160a01b031690565b610f48576040805160ff868116602083019081529282018b90526001600160a01b038a1660608301527f0f05f8598640816bc7963f9e84995cc362736f66a37eaca8293048e25aed4067989097610f2f96610ef7959294919390929190610eef81608081015b03601f1981018352826112be565b51902061326d565b610f1087610e558560ff165f52600860205260405f2090565b80546001600160a01b0319166001600160a01b03909216919091179055565b6040516001600160a01b039490941684521691602090a3005b63c45546f760e01b5f5260045ffd5b346104b6575f3660031901126104b65760206040517f2590c13a6bfb59ce1e1dfcbf973cec418117b8426141e0cc31959b3d7bfa2d938152f35b346104b6575f3660031901126104b65760206040517f8b6e6eebcf1e5aa625df96285186591a18b47d82a0e5344612aba13e51bc0e6f8152f35b346104b6575f3660031901126104b657608060018060a01b036013541660145460155460ff60165416916040519384526020840152604083015215156060820152f35b346104b65760203660031901126104b65760043561102b816104f9565b60018060a01b03165f526002602052602060ff60405f2054166040519015158152f35b346104b65760203660031901126104b65760043561106b816104f9565b6001600160a01b03811690811561062f575f5160206141d65f395f51905f526110af6040516020810190858252602081526110a76040826112be565b519020612def565b6110b881612ec3565b600980546001600160a01b031981166001600160a01b0395861617909155909216915f5160206141f65f395f51905f525f80a37f62e09f04681da780308095cdff046660f0b1e396888312a767499401693c03e55f80a3005b346104b6575f3660031901126104b6576020600354604051908152f35b346104b65760203660031901126104b657600435335f52600260205260ff60405f2054161561119457801561062f57335f8181526005602052604081208390557fe58dd23bcf790de89fbc05578bcc206ece8cb67dee1cf099fce6ff74d052ff3e9080a3005b633b63649d60e11b5f523360045260245ffd5b346104b6576101403660031901126104b6576111c1610d95565b6024356044359160a03660631901126104b657610104356001600160401b0381116104b6576111f4903690600401610678565b9061012435946001600160401b0386116104b657611219610018963690600401610678565b9590946123e4565b634e487b7160e01b5f52603260045260245ffd5b6007548110156112515760075f5260205f209060021b01905f90565b611221565b8054821015611251575f5260205f209060021b01905f90565b634e487b7160e01b5f52604160045260245ffd5b60a081019081106001600160401b0382111761129e57604052565b61126f565b608081019081106001600160401b0382111761129e57604052565b90601f801991011681019081106001600160401b0382111761129e57604052565b604051906112ee6080836112be565b565b906040516112fd81611283565b608060ff808395546001600160401b0381168552818160401c166020860152818160481c166040860152818160501c16606086015260581c1616910152565b346104b65760203660031901126104b6576004356007548110156104b65761136661010091611235565b506113dc60ff825416916001810154906113876003600283015492016112f0565b9160405194855260208501526040840152606083019060ff608080926001600160401b038151168552826020820151166020860152826040820151166040860152826060820151166060860152015116910152565bf35b346104b6575f3660031901126104b65760206040517fedb0239d3d518751089b6e176aa9d6d59832b2f29f85556f331dc42619252e628152f35b346104b6575f3660031901126104b6576020600f54604051908152f35b346104b65760203660031901126104b6576004355f52600d60205260c060405f2060ff81541690600181015490600281015460038201549060056004840154930154936040519515158652602086015260408501526060840152608083015260a0820152f35b346104b65760603660031901126104b6576004356024356001600160401b0381116104b6576114ce903690600401610678565b604435916001600160401b0383116104b6576114f1611517933690600401610678565b929091604051602081019061150f81610ee18a859190602083019252565b519020613383565b611529815f52600c60205260405f2090565b80546001600160401b038116156115c057604081901c60ff166115ac5760481c60ff1661159857805469ff0000000000000000001916690100000000000000000017815560010154907f4ef6805613a59a1bece0b99a00b945fffadc1bb793c7064706233d30fd438c765f80a3005b632863f91560e21b5f52600482905260245ffd5b633599e08d60e21b5f52600483905260245ffd5b633e426d5160e21b5f52600483905260245ffd5b6004359061ffff821682036104b657565b6024359061ffff821682036104b657565b346104b65760403660031901126104b6576116206116126115d4565b61161a6115e5565b9061262f565b6040518091602082016020835281518091526020604084019201905f5b81811061164b575050500390f35b9193509160206101006001926116bd6060885160ff81511684528581015186850152604081015160408501520151606083019060ff608080926001600160401b038151168552826020820151166020860152826040820151166040860152826060820151166060860152015116910152565b01940191019184939261163d565b346104b6575f3660031901126104b6576020604051610e108152f35b60c09060231901126104b657602490565b346104b6576101203660031901126104b657600435611716366116e7565b9060e4356001600160401b0381116104b657611736903690600401610678565b92610104356001600160401b0381116104b657611757903690600401610678565b908235611763816126e7565b806117be575b6117af576104909561179f95610ee161179061179a966040519283916020830195866126fb565b5190209485613499565b613c0d565b6040519081529081906020820190565b63137ec6d760e11b5f5260045ffd5b50602083013515611769565b346104b65760e03660031901126104b6576004356117e7366116e7565b611809604051602081019061180181610ee18688866126fb565b519020612e27565b9061181382612ec3565b8215611892575b7faa1bacadd202709f2df9c31faf4babdbb21a245021c22298bfcdf22861ca12c69161188d6118825f5160206141965f395f51905f5293865f52600d6020526118668160405f2061274a565b6040519485945f5160206141f65f395f51905f525f80a36126f1565b151582526020820190565b0390a2005b9150600e545f198114610d815760018101600e559161181a565b346104b6575f3660031901126104b6576020601054604051908152f35b346104b6576118d7366106a8565b91936001600160a01b03169190821561062f576119289461191593604051602081019182526020815261190b6040826112be565b519020948561359c565b5f5160206142365f395f51905f52612e97565b805f52600c60205260405f209060ff825460401c1661084d575f5160206142365f395f51905f525f52600b6020527f5248b41ce7bdc12ebe0248f44130be972d690f78fe7dbe1a76d984641d9dcfc25491821561083957815f5160206141b65f395f51905f5261082e5f5160206142365f395f51905f52938460016107fb6107ef60209a426121d5565b346104b6575f3660031901126104b65760206040515f5160206141965f395f51905f528152f35b346104b6576119e7366106a8565b92939091906001600160a01b0316801561062f575f80808093611a2f8888888c476040516020810191888352604082015260408152611a276060826112be565b51902061369f565b4790828215611a46575bf115611a4157005b612798565b506108fc611a39565b346104b65760203660031901126104b657600435611a6c816104f9565b6001600160a01b0316801561062f57611aa0604051602081019083825260208152611a986040826112be565b519020612e5f565b611aa981612ec3565b6011545f5160206142165f395f51905f5290611acd906001600160a01b0316610e6f565b601180546001600160a01b0319166001600160a01b038616179055915f5160206141f65f395f51905f525f80a36001600160a01b03167ff6879817b383066906e8355b81d5157ffe8bff151dd1946b33863aeede50ff985f80a3005b346104b6575f3660031901126104b6576020600e54604051908152f35b9181601f840112156104b6578235916001600160401b0383116104b657602083818601950101116104b657565b346104b65760a03660031901126104b6576004356024356001600160401b0381116104b657611ba6903690600401611b46565b9190604435926001600160401b0384116104b657611bcb610018943690600401611b46565b9160643593611bd9856104f9565b6084359561298c565b346104b6575f3660031901126104b65760206040517ffdc5f96508969628a00bce64abbf1ea989f16e791b70592a3122d67a7792e48c8152f35b346104b6575f3660031901126104b6576020600454604051908152f35b346104b65760603660031901126104b6576004356024356001600160401b0381116104b657611c6c903690600401610678565b906044356001600160401b0381116104b657611c8c903690600401610678565b92909184158015611d1f575b611d0557917fc33728fb6bc64ec1c5596c946e1406ccdfb7369404098c1d6a5f4a7a29c97b63949391611ce793604051602081019087825260208152611cdf6040826112be565b5190206137b5565b600354611cf382600355565b604080519182526020820192909252a1005b846001549063158589c560e11b5f5260045260245260445ffd5b506001548511611c98565b346104b6575f3660031901126104b65760206040517fa24d58aaa8deed8b2ff0e63d867e6fe155de046522ed61849f5647e59d04b6ba8152f35b346104b65760203660031901126104b6576004356001548110156104b65760015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601546040516001600160a01b039091168152602090f35b346104b6575f3660031901126104b65760206040517f5cdde72149ec19ce1ce0ecbedb38d9335aa5e1f8c43addf6e406b9c16e19f9478152f35b346104b6575f3660031901126104b65760206040515f5160206141d65f395f51905f528152f35b346104b6575f3660031901126104b6576020611e39612d1f565b604051908152f35b346104b6575f3660031901126104b6575f546040516001600160a01b039091168152602090f35b346104b65760203660031901126104b6576004355f52600b602052602060405f2054604051908152f35b346104b6575f3660031901126104b65760206040517fcb4f435a315262cdbbc1b22d576bc49b5e10e1516491e175d295831ff8a813058152f35b346104b657611eda366106a8565b6001600160a01b0385165f908152600260205260409020549294939290919060ff1615611f55576001600160a01b0384165f908152600560205260409020541561062f57604080516001600160a01b0386166020820190815261001897610ae8969093909290611f4d9082908101610ee1565b5190206138cb565b633b63649d60e11b5f526001600160a01b03841660045260245ffd5b634e487b7160e01b5f525f60045260245ffd5b916020908281520191905f5b818110611f9d5750505090565b9091926020806001928635611fb1816104f9565b848060a01b031681520194019101919091611f90565b929093611fed92608095989796988552602085015260a0604085015260a0840191611f84565b9460608201520152565b9493929160409261201d9260018060a01b03168752606060208801526060870191611f84565b930152565b6001600160401b03811161129e57601f01601f191660200190565b3d15612067573d9061204e82612022565b9161205c60405193846112be565b82523d5f602084013e565b606090565b1561207357565b60405162461bcd60e51b815260206004820152601c60248201527f53747261746567792064656c656761746563616c6c206661696c6564000000006044820152606490fd5b93929160209161201d91604087526040870191611f84565b969790979492949391936120f6610e6f610e628b610e558c5f52600860205260405f2090565b966001600160a01b038816156121b2577fc55043b6a137f66033384e3f6d9b80e72303eab38436f8fdb89899dc87ce53a2976121606121a1945f9485946121ad998f8f6121588f918f90610ee1908f604051958694602086019834948a611fc7565b5190206139e1565b61216a8b8b613d60565b60405161218f81610ee1898d8d60208501976303a81a5760e11b895260248601611ff7565b51915af461219b61203d565b5061206c565b604051938493846120b8565b0390a3565b635c7f4b4760e11b5f5260045ffd5b634e487b7160e01b5f52601160045260245ffd5b91908201809211610d8157565b35906001600160401b03821682036104b657565b60ff612252608080936001600160401b03612210826121e2565b1686528361222060208301610da5565b1660208701528361223360408301610da5565b1660408701528361224660608301610da5565b16606087015201610da5565b16910152565b91908260a09103126104b65760405161227081611283565b60806122bc818395612281816121e2565b855261228f60208201610da5565b60208601526122a060408201610da5565b60408601526122b160608201610da5565b606086015201610da5565b910152565b600754600160401b81101561129e578060016122e292016007556007611256565b9190916123c9576123af6080606060036112ee9560ff86511660ff198254161781556020860151600182015560408601516002820155019301516123466001600160401b0382511685906001600160401b03166001600160401b0319825416179055565b6020810151845461238a9160ff60401b1990911660409190911b68ff0000000000000000161760ff60408401511660ff60481b9060481b169060ff60481b19161790565b606082015160ff60501b1990911660509190911b60ff60501b16178455015160ff1690565b815460ff60581b191660589190911b60ff60581b16179055565b611f71565b90815260c0810192916112ee91602001906121f6565b959294909582156117af5761245d606494612491937fdcd264bd7d6d022cfcd2ef488637c26dba3344acfaad38a093f1755fe21085f5976040519960208b0160ff87169b8c82528d6040820152896060820152612444608082018c6121f6565b6101008152612455610120826112be565b519020613af7565b6124716124686112df565b60ff9092168252565b8660208201528260408201526124873685612258565b60608201526122c1565b6121ad604051928392836123ce565b6001600160401b03811161129e5760051b60200190565b6124c05f6124a0565b906124ce60405192836112be565b5f825281601f196124de5f6124a0565b01905f5b8281106124ee57505050565b6020906040516124fd816112a3565b5f81525f838201525f604082015260405161251781611283565b5f81525f848201525f60408201525f60608201525f60808201526060820152828285010152016124e2565b9061254c826124a0565b61255960405191826112be565b828152809261256a601f19916124a0565b01905f5b82811061257a57505050565b602090604051612589816112a3565b5f81525f838201525f60408201526040516125a381611283565b5f81525f848201525f60408201525f60608201525f608082015260608201528282850101520161256e565b9061ffff8091169116039061ffff8211610d8157565b80518210156112515760209160051b010190565b90604051612605816112a3565b60606122bc6003839560ff81541685526001810154602086015260028101546040860152016112f0565b6007549161ffff821692808410156126db578061ffff8316116126cf575b508261ffff821611156126c15761266e91612667916125ce565b61ffff1690565b61267781612542565b915f5b8281106126875750505090565b806126a561269f61269a600194866121d5565b611235565b506125f8565b6126af82876125e4565b526126ba81866125e4565b500161267a565b5050506126cc6124b7565b90565b61ffff9150165f61264d565b505050506126cc6124b7565b801515036104b657565b356126cc816126e7565b90929160a060c09160e084019584528035612715816126e7565b151560208501526020810135604085015260408101356060850152606081013560808501526080810135828501520135910152565b9060a0600591803561275b816126e7565b60ff801986541691151516178455602081013560018501556040810135600285015560608101356003850155608081013560048501550135910155565b6040513d5f823e3d90fd5b91906040838203126104b65782516127ba816126e7565b926020810151906001600160401b0382116104b6570181601f820112156104b6578051906127e782612022565b926127f560405194856112be565b828452602083830101116104b657815f9260208093018386015e8301015290565b908060209392818452848401375f828201840152601f01601f1916010190565b929061284f906126cc9593606086526060860191612816565b92600160208201526040818503910152612816565b9060a8116104b65760880190602090565b90610168116104b6576101480190602090565b90610198116104b6576101780190602090565b906101c8116104b6576101a80190602090565b906101f8116104b6576101d80190602090565b9061021c116104b6576102080190601490565b9061023c116104b65761021c0190602090565b90610244116104b65761023c0190600890565b359060208110612908575090565b5f199060200360031b1b1690565b356bffffffffffffffffffffffff19811692919060148210612936575050565b6bffffffffffffffffffffffff1960149290920360031b82901b16169150565b356001600160c01b0319811692919060088210612971575050565b6001600160c01b031960089290920360031b82901b16169150565b9091929495936012548015908115612d15575b50610bb8576001600160a01b03871695861561062f576011546129ca906001600160a01b0316610e6f565b916001600160a01b03831615612d06576129ff925f92836040518096819582946302bc2ce760e51b84528c8c60048601612836565b03925af1908115611a41575f905f92612ce1575b5015612cc357506102488310612cb457612a7690612a3a612a348585612864565b906128fa565b612a47612a348686612875565b612a54612a348787612888565b90612a62612a34888861289b565b92612a70612a3489896128ae565b94613e22565b83612abc612ab6612ab0612a9c612a96612a9088886128c1565b90612916565b60601c90565b95612aaa612a3482886128d4565b956128e7565b90612956565b60c01c90565b926001600160a01b031603612ca5578203612ca557600f54936001600160401b0382169480861115612c865750612af8610ac160165460ff1690565b612c545760145480861115612bd65750612baa907fd7f6e74f567cbc509ae5f7854bc05fd2a9b3c014f4aa28788ef99e0d8f2ecba69495612b49612b3a6112df565b6001600160a01b039093168352565b6020820152836040820152612b616060820160019052565b60609060018060a01b038151166bffffffffffffffffffffffff60a01b6013541617601355602081015160145560408101516015550151151560ff801960165416911617601655565b612bb960ff1960175416601755565b604080516001600160401b039290921682526020820192909252a2565b929350509214612be5575b5050565b6015548114612be1577fa3f0eabe92ef7bacb81dba904189dc163924ee16379f429441a4117441609fff91612c22600160ff196017541617601755565b612c4f60155492604051938493846040919493926001600160401b03606083019616825260208201520152565b0390a1565b612bb9907fd7f6e74f567cbc509ae5f7854bc05fd2a9b3c014f4aa28788ef99e0d8f2ecba69495612b49612b3a6112df565b636762eb4960e01b5f526004526001600160401b03821660245260445ffd5b63319c9a2160e21b5f5260045ffd5b632ffd02b360e11b5f5260045ffd5b805115612cd257805190602001fd5b63e1ac453160e01b5f5260045ffd5b9050612cff91503d805f833e612cf781836112be565b8101906127a3565b905f612a13565b63baa3de5f60e01b5f5260045ffd5b905042115f61299f565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f3d4a1189ec311cad4499197cf097eefb10346f2894cdd7cbbcb2d2a48001c91860408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a08152612db160c0826112be565b51902090565b60405160208101915f5160206142365f395f51905f528352604082015230606082015246608082015260808152612db160a0826112be565b60405160208101915f5160206141d65f395f51905f528352604082015230606082015246608082015260808152612db160a0826112be565b60405160208101915f5160206141965f395f51905f528352604082015230606082015246608082015260808152612db160a0826112be565b60405160208101915f5160206142165f395f51905f528352604082015230606082015246608082015260808152612db160a0826112be565b906040519060208201928352604082015230606082015246608082015260808152612db160a0826112be565b805f52600c60205260405f209081546001600160401b038116906001600160401b03821615612f4d57604081901c60ff166115ac5760481c60ff16611598576001600160401b0381164210612f27575050805460ff60401b1916600160401b179055565b63c504f34d60e01b5f526004919091526001600160401b0316602452504260445260645ffd5b82633e426d5160e21b5f5260045260245ffd5b91908110156112515760051b0190565b356126cc816104f9565b91908110156112515760051b81013590601e19813603018212156104b65701908135916001600160401b0383116104b65760200182360381136104b6579190565b929192612fc782612022565b91612fd560405193846112be565b8294818452818301116104b6578281602093845f960137010152565b5f5490949192919061300b906001600160a01b0316610e6f565b331480613162575b8061315a575b613146576003549381830361311557848310801561313d575b6131245761305160045480975f5160206141d65f395f51905f52614027565b925f945f5b8781106130775750505050505050506130726112ee9160010190565b600455565b61308a613085828585612f60565b612f70565b966001600160a01b03908116908816111561311557866130c7610ac16130c08360018060a01b03165f52600260205260405f2090565b5460ff1690565b6130fa576130ed610ac16130e66130df858a8a612f7a565b3691612fbb565b89846140a8565b6130fa5750600101613056565b633b63649d60e11b5f526001600160a01b031660045260245ffd5b630da1c57360e41b5f5260045ffd5b6378f4355360e11b5f526004839052602485905260445ffd5b50848210613032565b50505050506112ee61307260045460010190565b508015613019565b508115613013565b5f54909491929190613184906001600160a01b0316610e6f565b331480613265575b8061325d575b6131465760035493818303613115578483108015613254575b613124576131ca60045480975f5160206142165f395f51905f52614027565b925f945f5b8781106131eb5750505050505050506130726112ee9160010190565b6131f9613085828585612f60565b966001600160a01b039081169088161115613115578661322f610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613247610ac16130e66130df858a8a612f7a565b6130fa57506001016131cf565b508482106131ab565b508015613192565b50811561318c565b5f54909491929190613287906001600160a01b0316610e6f565b33148061337b575b80613373575b613146576003549381830361311557848310801561336a575b613124576132e060045480977f921db041069361e63fc63658404e32c96548fc5d6a72e7fe763cb3c8b370e3fd614027565b925f945f5b8781106133015750505050505050506130726112ee9160010190565b61330f613085828585612f60565b966001600160a01b0390811690881611156131155786613345610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa5761335d610ac16130e66130df858a8a612f7a565b6130fa57506001016132e5565b508482106132ae565b508015613295565b50811561328f565b5f5490949192919061339d906001600160a01b0316610e6f565b331480613491575b80613489575b6131465760035493818303613115578483108015613480575b613124576133f660045480977fcb4f435a315262cdbbc1b22d576bc49b5e10e1516491e175d295831ff8a81305614027565b925f945f5b8781106134175750505050505050506130726112ee9160010190565b613425613085828585612f60565b966001600160a01b039081169088161115613115578661345b610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613473610ac16130e66130df858a8a612f7a565b6130fa57506001016133fb565b508482106133c4565b5080156133ab565b5081156133a5565b5f549094919291906134b3906001600160a01b0316610e6f565b331480613594575b8061358c575b6131465760035493818303613115578483108015613583575b613124576134f960045480975f5160206141965f395f51905f52614027565b925f945f5b87811061351a5750505050505050506130726112ee9160010190565b613528613085828585612f60565b966001600160a01b039081169088161115613115578661355e610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613576610ac16130e66130df858a8a612f7a565b6130fa57506001016134fe565b508482106134da565b5080156134c1565b5081156134bb565b5f549094919291906135b6906001600160a01b0316610e6f565b331480613697575b8061368f575b6131465760035493818303613115578483108015613686575b613124576135fc60045480975f5160206142365f395f51905f52614027565b925f945f5b87811061361d5750505050505050506130726112ee9160010190565b61362b613085828585612f60565b966001600160a01b0390811690881611156131155786613661610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613679610ac16130e66130df858a8a612f7a565b6130fa5750600101613601565b508482106135dd565b5080156135c4565b5081156135be565b5f549094919291906136b9906001600160a01b0316610e6f565b3314806137ad575b806137a5575b613146576003549381830361311557848310801561379c575b6131245761371260045480977f2590c13a6bfb59ce1e1dfcbf973cec418117b8426141e0cc31959b3d7bfa2d93614027565b925f945f5b8781106137335750505050505050506130726112ee9160010190565b613741613085828585612f60565b966001600160a01b0390811690881611156131155786613777610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa5761378f610ac16130e66130df858a8a612f7a565b6130fa5750600101613717565b508482106136e0565b5080156136c7565b5081156136c1565b5f549094919291906137cf906001600160a01b0316610e6f565b3314806138c3575b806138bb575b61314657600354938183036131155784831080156138b2575b6131245761382860045480977f5cdde72149ec19ce1ce0ecbedb38d9335aa5e1f8c43addf6e406b9c16e19f947614027565b925f945f5b8781106138495750505050505050506130726112ee9160010190565b613857613085828585612f60565b966001600160a01b039081169088161115613115578661388d610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa576138a5610ac16130e66130df858a8a612f7a565b6130fa575060010161382d565b508482106137f6565b5080156137dd565b5081156137d7565b5f549094919291906138e5906001600160a01b0316610e6f565b3314806139d9575b806139d1575b61314657600354938183036131155784831080156139c8575b6131245761393e60045480977f1f9aa1ad5b6acb4043f0654345360b23371878df9b7f4802b13fcb8d3fbb745f614027565b925f945f5b87811061395f5750505050505050506130726112ee9160010190565b61396d613085828585612f60565b966001600160a01b03908116908816111561311557866139a3610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa576139bb610ac16130e66130df858a8a612f7a565b6130fa5750600101613943565b5084821061390c565b5080156138f3565b5081156138ed565b5f549094919291906139fb906001600160a01b0316610e6f565b331480613aef575b80613ae7575b6131465760035493818303613115578483108015613ade575b61312457613a5460045480977f3f98d537f24f3ae50e4a30e12fbf3e5c35cf6f40f4ce125c82c1b88e3e7cf3df614027565b925f945f5b878110613a755750505050505050506130726112ee9160010190565b613a83613085828585612f60565b966001600160a01b0390811690881611156131155786613ab9610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613ad1610ac16130e66130df858a8a612f7a565b6130fa5750600101613a59565b50848210613a22565b508015613a09565b508115613a03565b5f54909491929190613b11906001600160a01b0316610e6f565b331480613c05575b80613bfd575b6131465760035493818303613115578483108015613bf4575b61312457613b6a60045480977fedb0239d3d518751089b6e176aa9d6d59832b2f29f85556f331dc42619252e62614027565b925f945f5b878110613b8b5750505050505050506130726112ee9160010190565b613b99613085828585612f60565b966001600160a01b0390811690881611156131155786613bcf610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613be7610ac16130e66130df858a8a612f7a565b6130fa5750600101613b6f565b50848210613b38565b508015613b1f565b508115613b19565b613c24905f5160206141965f395f51905f52612e97565b90815f52600c60205260405f2060ff815460401c166115ac575f5160206141965f395f51905f525f52600b6020527f9b6d9405e2a268edd94615fe7f07c0d5d9dda2152c2e48f4e74379972af1c618548015613cab575f5160206141b65f395f51905f526121ad5f5160206141965f395f51905f52938460016107fb6107ef8a97426121d5565b6309913ab360e31b5f5260045260245ffd5b6001600160a01b0381165f8181526002602052604090205490919060ff1615613d4d576001600160a01b0381165f908152600560205260409020541561062f57600680546001600160a01b031916831790556001600160a01b03165f90815260056020526040902054907f2c8c895ef6e3978e12490ffd8cd3b92d4717b223562f851382f5daf74f587b515f80a3565b50633b63649d60e11b5f5260045260245ffd5b6007545f5b818110613d855763dfffe2f960e01b5f526004839052602484905260445ffd5b613d9161269f82611235565b8360ff8251161480613dba575b613dab5750600101613d65565b6040015160601c949350505050565b5084602082015114613d9e565b9060405160c081018181106001600160401b0382111761129e5760405260a06005829460ff81541615158452600181015460208501526002810154604085015260038101546060850152600481015460808501520154910152565b93929190613e40613e3b865f52600d60205260405f2090565b613dc7565b94613e4e610ac18751151590565b61401557506020850180511561062f5751808203613fd9575050604084015180151580613fcf575b613f91575050606083015180151580613f87575b613f49575050608082015180151580613f3f575b613f0157505060a0015180151580613ef7575b613eb9575050565b60405163fef6c5cf60e01b81526004810191909152602481019190915260606044820152600560648201526452544d523360d81b608482015260a490fd5b5080821415613eb1565b60405163fef6c5cf60e01b815260048101919091526024810191909152606060448201526005606482015264292a26a91960d91b608482015260a490fd5b5080821415613e9e565b60405163fef6c5cf60e01b81526004810191909152602481019190915260606044820152600560648201526452544d523160d81b608482015260a490fd5b5080821415613e8a565b60405163fef6c5cf60e01b815260048101919091526024810191909152606060448201526005606482015264052544d52360dc1b608482015260a490fd5b5080821415613e76565b60405163fef6c5cf60e01b81526004808201929092526024810192909252606060448301526064820152631354951160e21b608482015260a490fd5b6350dfe91360e01b5f5260045260245ffd5b916040519160208301937f4a3d56bf3b5708e5b633d12931f9923b37fde6895d6bd92957bbfa92cd00303985526040840152606083015260808201526080815261407260a0826112be565b51902061407d612d1f565b9060405190602082019261190160f01b84526022830152604282015260428152612db16062826112be565b90915f91906001600160a01b0382161561418d5760405192600484019460248501956044860192853b1561411157509186939160209593630b135d3f60e11b8852526040845281518501809260045afa9360443d01915afa9151630b135d3f60e11b1491161690565b9796505090508151806040146141685760411461412e5750505050565b60209293955060608201515f1a835260408201516060525b5f5201516040526020600160805f825afa511860601b3d11915f606052604052565b506020929395506040820151601b8160ff1c01845260018060ff1b0316606052614146565b505050505f9056feea4a6847c3f47fe0f98dcfe2e2c074e6cb42f6d74c367b33ae8516f537e775829cc91136b2c7668ecd202c7008f17e818e108b5448a7b7fd48bd2ca6b4aab51fb40912900bb80b6bc5e38d8489266de7299eedb40b03490214410117ef53ff9279883188dbf80e171cf94b3b44b6437b838158b1d3a5df6ccc709eeb7c5217296acb9fef2a4a1ecaa044f4c8979d9f48b0d5be623c860275be31c4cbd34c169cb2d153886d95f8f2d4836fb16c9fac869e1ce9cfc93d919a0f7dfe38439b9771a2646970667358221220e0e92d56df95f5865ed5237b33c5990684fc5c337264026f0c7f338483f1599a64736f6c634300081e0033"},"devdoc":{"details":"This contract acts as the governance layer and the vault registry. It manages the set of authorized operators, enforces quorum consensus for critical updates, and maintains the registry of deposit vaults across different chains. It combines immediate multi-sig actions for operational tasks with timelocked actions for high-risk configuration changes.","errors":{"InsufficientSignatures(uint256,uint256)":[{"params":{"provided":"The number of signatures provided.","required":"The current `quorumThreshold` required."}}],"InvalidDelay(uint256)":[{"params":{"delay":"The provided delay in seconds."}}],"InvalidQuorum(uint256,uint256)":[{"params":{"newQuorum":"The proposed threshold.","operatorCount":"The total number of registered operators."}}],"NotOperator(address)":[{"params":{"signer":"The address recovered from the signature."}}],"SignersNotSortedOrUnique()":[{"details":"Signatures must be sorted strictly ascending (A < B) to prevent duplicate counting in O(N)."}],"TimelockAlreadyCanceled(bytes32)":[{"params":{"opId":"The operation hash."}}],"TimelockAlreadyExecuted(bytes32)":[{"params":{"opId":"The operation hash."}}],"TimelockNotReady(bytes32,uint256,uint256)":[{"params":{"nowTs":"The current block timestamp.","opId":"The unique hash of the operation.","readyAt":"The timestamp when the operation becomes executable."}}],"TimelockUnknown(bytes32)":[{"params":{"opId":"The operation hash."}}],"VaultNotFound(uint256,uint256)":[{"params":{"routingId":"The routing ID of the vault.","vmId":"The Chain ID for EVM chains requested."}}]},"kind":"dev","methods":{"addVault(uint8,uint256,bytes32,(uint64,uint8,uint8,uint8,uint8),address[],bytes[])":{"details":"This list is append-only. New vaults can be added, but existing ones cannot be removed.","params":{"routingId":"The routing ID of the vault.","signatures":"Corresponding signatures.","signers":"Sorted array of signers.","vaultAddr":"The address of the vault (as bytes32).","vmId":"The Chain ID for EVM chains requested."}},"cancelTimelock(bytes32,address[],bytes[])":{"details":"Can be called at any time before execution to prevent a malicious or erroneous update.","params":{"opId":"The hash of the operation to cancel."}},"constructor":{"params":{"initialOperators":"The list of addresses that will form the initial governance council.","initialQuorumThreshold":"The number of signatures required for valid governance actions.","initialRegistryContract":"The initial Registry Contract address.","initialRiskManager":"The initial Risk Manager address."}},"domainSeparator()":{"returns":{"_0":"The domain separator hash."}},"executeRegistryContract(address)":{"params":{"newRegistry":"The address that was previously scheduled."}},"executeRiskManager(address)":{"params":{"newRiskManager":"The address that was previously scheduled."}},"getCouncilConfig()":{"details":"Let's operators query for 'k, n' thresholds and the current council member list\"."},"getLeader()":{"details":"When querying current leader, then the contract returns the active operator_pubkey and attested_pubkey."},"getVaults(uint16,uint16)":{"details":"The input types are intentionally `uint16` to preserve the function selector `0x9fd7285c` for backward compatibility with existing Rust clients.","params":{"end":"The end index (exclusive).","start":"The start index."},"returns":{"_0":"An array of Vault structs."}},"registerAdminUpdateStrategy(uint8,uint256,address,address[],bytes[])":{"details":"Used to define how the Credential Manager talks to L2s (e.g., via bridges). Only one strategy can be registered per chain.","params":{"routingId":"The routing ID of the vault.","signatures":"Corresponding signatures.","signers":"Sorted array of signers.","strategy":"The address of the strategy contract.","vmId":"The Chain ID for EVM chains requested."}},"registerAttestedKey(bytes32)":{"details":"Maps the attested_pubkey of a new CE joining the quorum.","params":{"newAttestedKey":"The address derived from the TEE's public key."}},"scheduleRegistryContract(address,address[],bytes[])":{"params":{"newRegistry":"The proposed new Registry address."},"returns":{"opId":"The unique hash of the scheduled operation."}},"scheduleRiskManager(address,address[],bytes[])":{"details":"The operation cannot be executed until `TIMELOCK_DELAY` has passed.","params":{"newRiskManager":"The proposed new Risk Manager address."},"returns":{"opId":"The unique hash of the scheduled operation."}},"scheduleUpdateAutomataVerifier(address,address[],bytes[])":{"details":"Operators vote to update the verifier and the update is proposed with a timelocked delay."},"setDepositVaultAdministrators(uint256,uint256,address[],uint256,address[],bytes[])":{"details":"This function acts as a proxy. It verifies the operator quorum locally, then delegate-calls the strategy to execute the actual logic (e.g., sending an L1->L2 message).","params":{"newAdministrators":"The list of new admin addresses for that vault.","newWithdrawalQuorum":"The new quorum requirement for that vault.","routingId":"The routing ID of the vault.","signatures":"Corresponding signatures.","signers":"Sorted array of signers.","vmId":"The Chain ID for EVM chains requested."}},"submitRestartProof(uint256,bytes,bytes,address,bytes32)":{"details":"We compare Epochs. The highest epoch wins.","params":{"checkpointHash":"The state hash being served.","newLeader":"The address claiming leadership.","tdxReportBody":"The 'Public Output' of the ZK Circuit (The TEE Quote Body).","zkProof":"The Groth16 proof bytes."}},"updateQuorumThreshold(uint256,address[],bytes[])":{"details":"Requires a quorum of the *current* operators to approve.","params":{"newThreshold":"The new minimum number of signatures.","signatures":"Corresponding signatures.","signers":"Sorted array of signers."}}},"stateVariables":{"OP_APPOINT_LEADER":{"details":"Used for appointing a leader in the absence of a leader - for bootstrap or emergency recovery."},"_ACTION_TYPEHASH":{"details":"Generic Action typehash used for all governance signatures. Structure: Action(bytes32 opType, bytes32 paramsHash, uint256 nonce)"},"_EIP712_DOMAIN_TYPEHASH":{"details":"EIP-712 Domain Separator typehash."},"_NAME_HASH":{"details":"EIP-712 name hash for this contract."},"_VERSION_HASH":{"details":"EIP-712 version hash."},"adminUpdateStrategies":{"details":"Used to abstract cross-chain messaging logic (e.g., LayerZero, Optimism Messenger)."},"epoch":{"details":"Incremented on every successful restart."},"governanceNonce":{"details":"Included in every signed hash to strictly order operations and prevent replay attacks."},"latestCheckpointHash":{"details":"New nodes verify this hash against the leader's data to ensure they are on the correct fork."},"leader":{"details":"The leader is responsible for coordinating the clearing engine."},"operatorToAttestedKey":{"details":"Used to verify that a TEE signature belongs to a specific operator."},"operators":{"details":"These keys form the root of trust for the system."},"timelockDelayFor":{"details":"e.g., OP_SET_REGISTRY -> 72 hours."},"vaults":{"details":"This list is strictly append-only; vaults cannot be removed to prevent history modification."}},"title":"CredentialManager","version":1},"methodIdentifiers":{"GATHERING_DURATION()":"0xa6aac513","OP_ADD_VAULT()":"0x90054742","OP_APPOINT_LEADER()":"0x4e970c8c","OP_CANCEL_TIMELOCK()":"0xfc0e2ba7","OP_MANAGE_PROFILE()":"0xb7635fb8","OP_REGISTER_STRATEGY()":"0x333bef22","OP_RESTART()":"0xd8a0bebf","OP_SET_AUTOMATA_VERIFIER()":"0x2d4ab28d","OP_SET_DELAY()":"0xe0913aff","OP_SET_MEASUREMENTS()":"0x6583c37a","OP_SET_QUORUM()":"0xf5949cd6","OP_SET_REGISTRY()":"0x1bc12e07","OP_SET_RISK_MANAGER()":"0xf5b68c67","OP_SET_VAULT_ADMINS()":"0x26ddc1ba","OP_WITHDRAW()":"0x5f250f69","addVault(uint8,uint256,bytes32,(uint64,uint8,uint8,uint8,uint8),address[],bytes[])":"0x81392328","admin()":"0xf851a440","adminUpdateStrategies(uint256,uint256)":"0x3174b727","appointLeader(address,address[],bytes[])":"0xfdeabe1f","automataVerifier()":"0x280cd09d","bestCandidate()":"0x669f6f35","cancelTimelock(bytes32,address[],bytes[])":"0x9d3e015a","domainSeparator()":"0xf698da25","epoch()":"0x900cf0cf","executeManageProfile(uint256,(bool,bytes32,bytes32,bytes32,bytes32,bytes32))":"0xae5c8bfb","executeRegistryContract(address)":"0x24242e77","executeRiskManager(address)":"0x6dfb32aa","executeUpdateAutomataVerifier(address)":"0xc7d06b54","getCouncilConfig()":"0x04235842","getLeader()":"0x4c051f14","getVaults(uint16,uint16)":"0x9fd7285c","governanceNonce()":"0xd9be832c","initiateRestart()":"0x5cc79144","isOperator(address)":"0x6d70f7ae","isRestartAmbiguous()":"0x1276bcc5","latestCheckpointHash()":"0xb34eb182","leader()":"0x40eedabb","measurementProfiles(uint256)":"0x95c82559","nextProfileId()":"0xcd1d81ff","operatorToAttestedKey(address)":"0x1ac4d079","operators(uint256)":"0xe28d4906","quorumThreshold()":"0x7b7a91dd","registerAdminUpdateStrategy(uint8,uint256,address,address[],bytes[])":"0x5d3ae390","registerAttestedKey(bytes32)":"0x7f0152a8","registryContract()":"0x28c1f99b","resolveRestart()":"0x35cfd9eb","restartGatheringDeadline()":"0x127f49ad","riskManager()":"0x47842663","scheduleManageProfile(uint256,(bool,bytes32,bytes32,bytes32,bytes32,bytes32),address[],bytes[])":"0xacfacc86","scheduleRegistryContract(address,address[],bytes[])":"0xb5ed8b12","scheduleRiskManager(address,address[],bytes[])":"0x2808e92f","scheduleUpdateAutomataVerifier(address,address[],bytes[])":"0x281cbdd4","setDepositVaultAdministrators(uint256,uint256,address[],uint256,address[],bytes[])":"0x413721f6","submitRestartProof(uint256,bytes,bytes,address,bytes32)":"0xce0b1302","timelockDelayFor(bytes32)":"0xfb834493","timelockOps(bytes32)":"0x31709520","updateQuorumThreshold(uint256,address[],bytes[])":"0xdd6fbaa2","vaults(uint256)":"0x8c64ea4a","withdraw(address,address[],bytes[])":"0xbe223838"},"runtimeBytecode":{"bytecode":"0x6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c806304235842146103c95780631276bcc5146103c4578063127f49ad146103bf5780631ac4d079146103ba5780631bc12e07146103b557806324242e77146103b057806326ddc1ba146103ab5780632808e92f146103a6578063280cd09d146103a1578063281cbdd41461039c57806328c1f99b146103975780632d4ab28d14610392578063317095201461038d5780633174b72714610388578063333bef221461038357806335cfd9eb1461037e57806340eedabb14610379578063413721f614610374578063478426631461036f5780634c051f141461036a5780634e970c8c146103655780635cc79144146103605780635d3ae3901461035b5780635f250f69146103565780636583c37a14610351578063669f6f351461034c5780636d70f7ae146103475780636dfb32aa146103425780637b7a91dd1461033d5780637f0152a81461033857806381392328146103335780638c64ea4a1461032e5780639005474214610329578063900cf0cf1461032457806395c825591461031f5780639d3e015a1461031a5780639fd7285c14610315578063a6aac51314610310578063acfacc861461030b578063ae5c8bfb14610306578063b34eb18214610301578063b5ed8b12146102fc578063b7635fb8146102f7578063be223838146102f2578063c7d06b54146102ed578063cd1d81ff146102e8578063ce0b1302146102e3578063d8a0bebf146102de578063d9be832c146102d9578063dd6fbaa2146102d4578063e0913aff146102cf578063e28d4906146102ca578063f5949cd6146102c5578063f5b68c67146102c0578063f698da25146102bb578063f851a440146102b6578063fb834493146102b1578063fc0e2ba7146102ac5763fdeabe1f0361000e57611ecc565b611e92565b611e68565b611e41565b611e1f565b611df8565b611dbe565b611d64565b611d2a565b611c39565b611c1c565b611be2565b611b73565b611b29565b611a4f565b6119d9565b6119b2565b6118c9565b6118ac565b6117ca565b6116f8565b6116cb565b6115f6565b61149b565b611435565b611418565b6113de565b61133c565b6111a7565b61112e565b611111565b61104e565b61100e565b610fcb565b610f91565b610f57565b610db3565b610d0b565b610cd1565b610c9c565b610c74565b610bef565b610bc7565b610a92565b610a58565b610a18565b6109bf565b610998565b610970565b610887565b61085f565b610706565b61063e565b61056c565b610545565b61050a565b6104dc565b6104ba565b610422565b9093929193606082016060835281518091526020608084019201905f5b81811061040357505050906040919460208201520152565b82516001600160a01b03168452602093840193909201916001016103eb565b346104b6575f3660031901126104b65760035460015460405190602082828152019060015f52827fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65f5b838110610494575050610484906104909303846112be565b604051938493846103ce565b0390f35b81546001600160a01b031685526020909401938592506001918201910161046c565b5f80fd5b346104b6575f3660031901126104b657602060ff601754166040519015158152f35b346104b6575f3660031901126104b6576020601254604051908152f35b6001600160a01b038116036104b657565b346104b65760203660031901126104b657600435610527816104f9565b60018060a01b03165f526005602052602060405f2054604051908152f35b346104b6575f3660031901126104b65760206040515f5160206142365f395f51905f528152f35b346104b65760203660031901126104b657600435610589816104f9565b6001600160a01b03811690811561062f575f5160206142365f395f51905f526105cd6040516020810190858252602081526105c56040826112be565b519020612db7565b6105d681612ec3565b600a80546001600160a01b031981166001600160a01b0395861617909155909216915f5160206141f65f395f51905f525f80a37f482b97c53e48ffa324a976e2738053e9aff6eee04d8aac63b10e19411d869b825f80a3005b63d92e233d60e01b5f5260045ffd5b346104b6575f3660031901126104b65760206040517f3f98d537f24f3ae50e4a30e12fbf3e5c35cf6f40f4ce125c82c1b88e3e7cf3df8152f35b9181601f840112156104b6578235916001600160401b0383116104b6576020808501948460051b0101116104b657565b9060606003198301126104b6576004356106c1816104f9565b916024356001600160401b0381116104b657816106e091600401610678565b92909291604435906001600160401b0382116104b65761070291600401610678565b9091565b346104b657610714366106a8565b91936001600160a01b03169190821561062f57610765946107529360405160208101918252602081526107486040826112be565b5190209485612ff1565b5f5160206141d65f395f51905f52612e97565b805f52600c60205260405f209060ff825460401c1661084d575f5160206141d65f395f51905f525f52600b6020527ffc320c8b7cd913048d0600d8f8fbdd9fd65e3dee2c1f3796e3abba8cc47fa0475491821561083957815f5160206141b65f395f51905f5261082e5f5160206141d65f395f51905f52938460016107fb6107ef60209a426121d5565b6001600160401b031690565b835469ffffffffffffffffffff19166001600160401b039190911690811784559201556040519081529081906020820190565b0390a3604051908152f35b6309913ab360e31b5f52600483905260245ffd5b633599e08d60e21b5f5260045260245ffd5b346104b6575f3660031901126104b6576011546040516001600160a01b039091168152602090f35b346104b657610895366106a8565b91936001600160a01b03169190821561062f576108e6946108d39360405160208101918252602081526108c96040826112be565b519020948561316a565b5f5160206142165f395f51905f52612e97565b805f52600c60205260405f209060ff825460401c1661084d575f5160206142165f395f51905f525f52600b6020527f5585c2bd0ffb4796fa70abc2a0b1f92173aa4b9f7e1b37d256fd2a975c5abcfa5491821561083957815f5160206141b65f395f51905f5261082e5f5160206142165f395f51905f52938460016107fb6107ef60209a426121d5565b346104b6575f3660031901126104b657600a546040516001600160a01b039091168152602090f35b346104b6575f3660031901126104b65760206040515f5160206142165f395f51905f528152f35b346104b65760203660031901126104b6576004355f52600c602052608060405f206001815491015460ff604051926001600160401b0381168452818160401c161515602085015260481c16151560408301526060820152f35b346104b65760403660031901126104b657600435602435905f52600860205260405f20905f52602052602060018060a01b0360405f205416604051908152f35b346104b6575f3660031901126104b65760206040517f921db041069361e63fc63658404e32c96548fc5d6a72e7fe763cb3c8b370e3fd8152f35b346104b6575f3660031901126104b6576012548015610bb857421115610ba957610ac5610ac160165460ff1690565b1590565b610b9a5760175460ff16610b8b57601354610aed906001600160a01b0316613cbd565b613cbd565b610af8601554601055565b610b03601454600f55565b610b0c5f601255565b610b215f6013555f6014555f6015555f601655565b600f546010546040805183815260208101929092527f88cac99f10d8167541407023871a1cc0d797dc75e5b23f3f9f54aaf445f5602c91a16006546001600160a01b03167fd7936f419066f72741af39dde15237d9aed55a0d1d9ab0cb3280569b42c3d8f35f80a3005b6363f5b90b60e11b5f5260045ffd5b63dcd4760160e01b5f5260045ffd5b63285f264160e21b5f5260045ffd5b63cbd2c74d60e01b5f5260045ffd5b346104b6575f3660031901126104b6576006546040516001600160a01b039091168152602090f35b60c03660031901126104b6576004356024356044356001600160401b0381116104b657610c20903690600401610678565b909290606435906084356001600160401b0381116104b657610c46903690600401610678565b92909160a435966001600160401b0388116104b657610c6c610018983690600401610678565b9790966120d0565b346104b6575f3660031901126104b6576009546040516001600160a01b039091168152602090f35b346104b6575f3660031901126104b657604060018060a01b0360065416805f526005602052815f205482519182526020820152f35b346104b6575f3660031901126104b65760206040517f1f9aa1ad5b6acb4043f0654345360b23371878df9b7f4802b13fcb8d3fbb745f8152f35b346104b6575f3660031901126104b6576012544210610d8657610e104201804211610d8157601255610d485f6013555f6014555f6015555f601655565b60ff19601754166017557f3d364c9a6ad0fb8014a11c487ec342f3a0aaf1a55973fc1bb7353ab6824a358f6020601254604051908152a1005b6121c1565b6301fd8f7b60e41b5f5260045ffd5b6004359060ff821682036104b657565b359060ff821682036104b657565b346104b65760a03660031901126104b657610dcc610d95565b60243590604435610ddc816104f9565b6064356001600160401b0381116104b657610dfb903690600401610678565b9190926084356001600160401b0381116104b657610e1d903690600401610678565b6001600160a01b038416959094919390861561062f57610e7b610e6f610e6f610e628b610e558960ff165f52600860205260405f2090565b905f5260205260405f2090565b546001600160a01b031690565b6001600160a01b031690565b610f48576040805160ff868116602083019081529282018b90526001600160a01b038a1660608301527f0f05f8598640816bc7963f9e84995cc362736f66a37eaca8293048e25aed4067989097610f2f96610ef7959294919390929190610eef81608081015b03601f1981018352826112be565b51902061326d565b610f1087610e558560ff165f52600860205260405f2090565b80546001600160a01b0319166001600160a01b03909216919091179055565b6040516001600160a01b039490941684521691602090a3005b63c45546f760e01b5f5260045ffd5b346104b6575f3660031901126104b65760206040517f2590c13a6bfb59ce1e1dfcbf973cec418117b8426141e0cc31959b3d7bfa2d938152f35b346104b6575f3660031901126104b65760206040517f8b6e6eebcf1e5aa625df96285186591a18b47d82a0e5344612aba13e51bc0e6f8152f35b346104b6575f3660031901126104b657608060018060a01b036013541660145460155460ff60165416916040519384526020840152604083015215156060820152f35b346104b65760203660031901126104b65760043561102b816104f9565b60018060a01b03165f526002602052602060ff60405f2054166040519015158152f35b346104b65760203660031901126104b65760043561106b816104f9565b6001600160a01b03811690811561062f575f5160206141d65f395f51905f526110af6040516020810190858252602081526110a76040826112be565b519020612def565b6110b881612ec3565b600980546001600160a01b031981166001600160a01b0395861617909155909216915f5160206141f65f395f51905f525f80a37f62e09f04681da780308095cdff046660f0b1e396888312a767499401693c03e55f80a3005b346104b6575f3660031901126104b6576020600354604051908152f35b346104b65760203660031901126104b657600435335f52600260205260ff60405f2054161561119457801561062f57335f8181526005602052604081208390557fe58dd23bcf790de89fbc05578bcc206ece8cb67dee1cf099fce6ff74d052ff3e9080a3005b633b63649d60e11b5f523360045260245ffd5b346104b6576101403660031901126104b6576111c1610d95565b6024356044359160a03660631901126104b657610104356001600160401b0381116104b6576111f4903690600401610678565b9061012435946001600160401b0386116104b657611219610018963690600401610678565b9590946123e4565b634e487b7160e01b5f52603260045260245ffd5b6007548110156112515760075f5260205f209060021b01905f90565b611221565b8054821015611251575f5260205f209060021b01905f90565b634e487b7160e01b5f52604160045260245ffd5b60a081019081106001600160401b0382111761129e57604052565b61126f565b608081019081106001600160401b0382111761129e57604052565b90601f801991011681019081106001600160401b0382111761129e57604052565b604051906112ee6080836112be565b565b906040516112fd81611283565b608060ff808395546001600160401b0381168552818160401c166020860152818160481c166040860152818160501c16606086015260581c1616910152565b346104b65760203660031901126104b6576004356007548110156104b65761136661010091611235565b506113dc60ff825416916001810154906113876003600283015492016112f0565b9160405194855260208501526040840152606083019060ff608080926001600160401b038151168552826020820151166020860152826040820151166040860152826060820151166060860152015116910152565bf35b346104b6575f3660031901126104b65760206040517fedb0239d3d518751089b6e176aa9d6d59832b2f29f85556f331dc42619252e628152f35b346104b6575f3660031901126104b6576020600f54604051908152f35b346104b65760203660031901126104b6576004355f52600d60205260c060405f2060ff81541690600181015490600281015460038201549060056004840154930154936040519515158652602086015260408501526060840152608083015260a0820152f35b346104b65760603660031901126104b6576004356024356001600160401b0381116104b6576114ce903690600401610678565b604435916001600160401b0383116104b6576114f1611517933690600401610678565b929091604051602081019061150f81610ee18a859190602083019252565b519020613383565b611529815f52600c60205260405f2090565b80546001600160401b038116156115c057604081901c60ff166115ac5760481c60ff1661159857805469ff0000000000000000001916690100000000000000000017815560010154907f4ef6805613a59a1bece0b99a00b945fffadc1bb793c7064706233d30fd438c765f80a3005b632863f91560e21b5f52600482905260245ffd5b633599e08d60e21b5f52600483905260245ffd5b633e426d5160e21b5f52600483905260245ffd5b6004359061ffff821682036104b657565b6024359061ffff821682036104b657565b346104b65760403660031901126104b6576116206116126115d4565b61161a6115e5565b9061262f565b6040518091602082016020835281518091526020604084019201905f5b81811061164b575050500390f35b9193509160206101006001926116bd6060885160ff81511684528581015186850152604081015160408501520151606083019060ff608080926001600160401b038151168552826020820151166020860152826040820151166040860152826060820151166060860152015116910152565b01940191019184939261163d565b346104b6575f3660031901126104b6576020604051610e108152f35b60c09060231901126104b657602490565b346104b6576101203660031901126104b657600435611716366116e7565b9060e4356001600160401b0381116104b657611736903690600401610678565b92610104356001600160401b0381116104b657611757903690600401610678565b908235611763816126e7565b806117be575b6117af576104909561179f95610ee161179061179a966040519283916020830195866126fb565b5190209485613499565b613c0d565b6040519081529081906020820190565b63137ec6d760e11b5f5260045ffd5b50602083013515611769565b346104b65760e03660031901126104b6576004356117e7366116e7565b611809604051602081019061180181610ee18688866126fb565b519020612e27565b9061181382612ec3565b8215611892575b7faa1bacadd202709f2df9c31faf4babdbb21a245021c22298bfcdf22861ca12c69161188d6118825f5160206141965f395f51905f5293865f52600d6020526118668160405f2061274a565b6040519485945f5160206141f65f395f51905f525f80a36126f1565b151582526020820190565b0390a2005b9150600e545f198114610d815760018101600e559161181a565b346104b6575f3660031901126104b6576020601054604051908152f35b346104b6576118d7366106a8565b91936001600160a01b03169190821561062f576119289461191593604051602081019182526020815261190b6040826112be565b519020948561359c565b5f5160206142365f395f51905f52612e97565b805f52600c60205260405f209060ff825460401c1661084d575f5160206142365f395f51905f525f52600b6020527f5248b41ce7bdc12ebe0248f44130be972d690f78fe7dbe1a76d984641d9dcfc25491821561083957815f5160206141b65f395f51905f5261082e5f5160206142365f395f51905f52938460016107fb6107ef60209a426121d5565b346104b6575f3660031901126104b65760206040515f5160206141965f395f51905f528152f35b346104b6576119e7366106a8565b92939091906001600160a01b0316801561062f575f80808093611a2f8888888c476040516020810191888352604082015260408152611a276060826112be565b51902061369f565b4790828215611a46575bf115611a4157005b612798565b506108fc611a39565b346104b65760203660031901126104b657600435611a6c816104f9565b6001600160a01b0316801561062f57611aa0604051602081019083825260208152611a986040826112be565b519020612e5f565b611aa981612ec3565b6011545f5160206142165f395f51905f5290611acd906001600160a01b0316610e6f565b601180546001600160a01b0319166001600160a01b038616179055915f5160206141f65f395f51905f525f80a36001600160a01b03167ff6879817b383066906e8355b81d5157ffe8bff151dd1946b33863aeede50ff985f80a3005b346104b6575f3660031901126104b6576020600e54604051908152f35b9181601f840112156104b6578235916001600160401b0383116104b657602083818601950101116104b657565b346104b65760a03660031901126104b6576004356024356001600160401b0381116104b657611ba6903690600401611b46565b9190604435926001600160401b0384116104b657611bcb610018943690600401611b46565b9160643593611bd9856104f9565b6084359561298c565b346104b6575f3660031901126104b65760206040517ffdc5f96508969628a00bce64abbf1ea989f16e791b70592a3122d67a7792e48c8152f35b346104b6575f3660031901126104b6576020600454604051908152f35b346104b65760603660031901126104b6576004356024356001600160401b0381116104b657611c6c903690600401610678565b906044356001600160401b0381116104b657611c8c903690600401610678565b92909184158015611d1f575b611d0557917fc33728fb6bc64ec1c5596c946e1406ccdfb7369404098c1d6a5f4a7a29c97b63949391611ce793604051602081019087825260208152611cdf6040826112be565b5190206137b5565b600354611cf382600355565b604080519182526020820192909252a1005b846001549063158589c560e11b5f5260045260245260445ffd5b506001548511611c98565b346104b6575f3660031901126104b65760206040517fa24d58aaa8deed8b2ff0e63d867e6fe155de046522ed61849f5647e59d04b6ba8152f35b346104b65760203660031901126104b6576004356001548110156104b65760015f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601546040516001600160a01b039091168152602090f35b346104b6575f3660031901126104b65760206040517f5cdde72149ec19ce1ce0ecbedb38d9335aa5e1f8c43addf6e406b9c16e19f9478152f35b346104b6575f3660031901126104b65760206040515f5160206141d65f395f51905f528152f35b346104b6575f3660031901126104b6576020611e39612d1f565b604051908152f35b346104b6575f3660031901126104b6575f546040516001600160a01b039091168152602090f35b346104b65760203660031901126104b6576004355f52600b602052602060405f2054604051908152f35b346104b6575f3660031901126104b65760206040517fcb4f435a315262cdbbc1b22d576bc49b5e10e1516491e175d295831ff8a813058152f35b346104b657611eda366106a8565b6001600160a01b0385165f908152600260205260409020549294939290919060ff1615611f55576001600160a01b0384165f908152600560205260409020541561062f57604080516001600160a01b0386166020820190815261001897610ae8969093909290611f4d9082908101610ee1565b5190206138cb565b633b63649d60e11b5f526001600160a01b03841660045260245ffd5b634e487b7160e01b5f525f60045260245ffd5b916020908281520191905f5b818110611f9d5750505090565b9091926020806001928635611fb1816104f9565b848060a01b031681520194019101919091611f90565b929093611fed92608095989796988552602085015260a0604085015260a0840191611f84565b9460608201520152565b9493929160409261201d9260018060a01b03168752606060208801526060870191611f84565b930152565b6001600160401b03811161129e57601f01601f191660200190565b3d15612067573d9061204e82612022565b9161205c60405193846112be565b82523d5f602084013e565b606090565b1561207357565b60405162461bcd60e51b815260206004820152601c60248201527f53747261746567792064656c656761746563616c6c206661696c6564000000006044820152606490fd5b93929160209161201d91604087526040870191611f84565b969790979492949391936120f6610e6f610e628b610e558c5f52600860205260405f2090565b966001600160a01b038816156121b2577fc55043b6a137f66033384e3f6d9b80e72303eab38436f8fdb89899dc87ce53a2976121606121a1945f9485946121ad998f8f6121588f918f90610ee1908f604051958694602086019834948a611fc7565b5190206139e1565b61216a8b8b613d60565b60405161218f81610ee1898d8d60208501976303a81a5760e11b895260248601611ff7565b51915af461219b61203d565b5061206c565b604051938493846120b8565b0390a3565b635c7f4b4760e11b5f5260045ffd5b634e487b7160e01b5f52601160045260245ffd5b91908201809211610d8157565b35906001600160401b03821682036104b657565b60ff612252608080936001600160401b03612210826121e2565b1686528361222060208301610da5565b1660208701528361223360408301610da5565b1660408701528361224660608301610da5565b16606087015201610da5565b16910152565b91908260a09103126104b65760405161227081611283565b60806122bc818395612281816121e2565b855261228f60208201610da5565b60208601526122a060408201610da5565b60408601526122b160608201610da5565b606086015201610da5565b910152565b600754600160401b81101561129e578060016122e292016007556007611256565b9190916123c9576123af6080606060036112ee9560ff86511660ff198254161781556020860151600182015560408601516002820155019301516123466001600160401b0382511685906001600160401b03166001600160401b0319825416179055565b6020810151845461238a9160ff60401b1990911660409190911b68ff0000000000000000161760ff60408401511660ff60481b9060481b169060ff60481b19161790565b606082015160ff60501b1990911660509190911b60ff60501b16178455015160ff1690565b815460ff60581b191660589190911b60ff60581b16179055565b611f71565b90815260c0810192916112ee91602001906121f6565b959294909582156117af5761245d606494612491937fdcd264bd7d6d022cfcd2ef488637c26dba3344acfaad38a093f1755fe21085f5976040519960208b0160ff87169b8c82528d6040820152896060820152612444608082018c6121f6565b6101008152612455610120826112be565b519020613af7565b6124716124686112df565b60ff9092168252565b8660208201528260408201526124873685612258565b60608201526122c1565b6121ad604051928392836123ce565b6001600160401b03811161129e5760051b60200190565b6124c05f6124a0565b906124ce60405192836112be565b5f825281601f196124de5f6124a0565b01905f5b8281106124ee57505050565b6020906040516124fd816112a3565b5f81525f838201525f604082015260405161251781611283565b5f81525f848201525f60408201525f60608201525f60808201526060820152828285010152016124e2565b9061254c826124a0565b61255960405191826112be565b828152809261256a601f19916124a0565b01905f5b82811061257a57505050565b602090604051612589816112a3565b5f81525f838201525f60408201526040516125a381611283565b5f81525f848201525f60408201525f60608201525f608082015260608201528282850101520161256e565b9061ffff8091169116039061ffff8211610d8157565b80518210156112515760209160051b010190565b90604051612605816112a3565b60606122bc6003839560ff81541685526001810154602086015260028101546040860152016112f0565b6007549161ffff821692808410156126db578061ffff8316116126cf575b508261ffff821611156126c15761266e91612667916125ce565b61ffff1690565b61267781612542565b915f5b8281106126875750505090565b806126a561269f61269a600194866121d5565b611235565b506125f8565b6126af82876125e4565b526126ba81866125e4565b500161267a565b5050506126cc6124b7565b90565b61ffff9150165f61264d565b505050506126cc6124b7565b801515036104b657565b356126cc816126e7565b90929160a060c09160e084019584528035612715816126e7565b151560208501526020810135604085015260408101356060850152606081013560808501526080810135828501520135910152565b9060a0600591803561275b816126e7565b60ff801986541691151516178455602081013560018501556040810135600285015560608101356003850155608081013560048501550135910155565b6040513d5f823e3d90fd5b91906040838203126104b65782516127ba816126e7565b926020810151906001600160401b0382116104b6570181601f820112156104b6578051906127e782612022565b926127f560405194856112be565b828452602083830101116104b657815f9260208093018386015e8301015290565b908060209392818452848401375f828201840152601f01601f1916010190565b929061284f906126cc9593606086526060860191612816565b92600160208201526040818503910152612816565b9060a8116104b65760880190602090565b90610168116104b6576101480190602090565b90610198116104b6576101780190602090565b906101c8116104b6576101a80190602090565b906101f8116104b6576101d80190602090565b9061021c116104b6576102080190601490565b9061023c116104b65761021c0190602090565b90610244116104b65761023c0190600890565b359060208110612908575090565b5f199060200360031b1b1690565b356bffffffffffffffffffffffff19811692919060148210612936575050565b6bffffffffffffffffffffffff1960149290920360031b82901b16169150565b356001600160c01b0319811692919060088210612971575050565b6001600160c01b031960089290920360031b82901b16169150565b9091929495936012548015908115612d15575b50610bb8576001600160a01b03871695861561062f576011546129ca906001600160a01b0316610e6f565b916001600160a01b03831615612d06576129ff925f92836040518096819582946302bc2ce760e51b84528c8c60048601612836565b03925af1908115611a41575f905f92612ce1575b5015612cc357506102488310612cb457612a7690612a3a612a348585612864565b906128fa565b612a47612a348686612875565b612a54612a348787612888565b90612a62612a34888861289b565b92612a70612a3489896128ae565b94613e22565b83612abc612ab6612ab0612a9c612a96612a9088886128c1565b90612916565b60601c90565b95612aaa612a3482886128d4565b956128e7565b90612956565b60c01c90565b926001600160a01b031603612ca5578203612ca557600f54936001600160401b0382169480861115612c865750612af8610ac160165460ff1690565b612c545760145480861115612bd65750612baa907fd7f6e74f567cbc509ae5f7854bc05fd2a9b3c014f4aa28788ef99e0d8f2ecba69495612b49612b3a6112df565b6001600160a01b039093168352565b6020820152836040820152612b616060820160019052565b60609060018060a01b038151166bffffffffffffffffffffffff60a01b6013541617601355602081015160145560408101516015550151151560ff801960165416911617601655565b612bb960ff1960175416601755565b604080516001600160401b039290921682526020820192909252a2565b929350509214612be5575b5050565b6015548114612be1577fa3f0eabe92ef7bacb81dba904189dc163924ee16379f429441a4117441609fff91612c22600160ff196017541617601755565b612c4f60155492604051938493846040919493926001600160401b03606083019616825260208201520152565b0390a1565b612bb9907fd7f6e74f567cbc509ae5f7854bc05fd2a9b3c014f4aa28788ef99e0d8f2ecba69495612b49612b3a6112df565b636762eb4960e01b5f526004526001600160401b03821660245260445ffd5b63319c9a2160e21b5f5260045ffd5b632ffd02b360e11b5f5260045ffd5b805115612cd257805190602001fd5b63e1ac453160e01b5f5260045ffd5b9050612cff91503d805f833e612cf781836112be565b8101906127a3565b905f612a13565b63baa3de5f60e01b5f5260045ffd5b905042115f61299f565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f3d4a1189ec311cad4499197cf097eefb10346f2894cdd7cbbcb2d2a48001c91860408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a08152612db160c0826112be565b51902090565b60405160208101915f5160206142365f395f51905f528352604082015230606082015246608082015260808152612db160a0826112be565b60405160208101915f5160206141d65f395f51905f528352604082015230606082015246608082015260808152612db160a0826112be565b60405160208101915f5160206141965f395f51905f528352604082015230606082015246608082015260808152612db160a0826112be565b60405160208101915f5160206142165f395f51905f528352604082015230606082015246608082015260808152612db160a0826112be565b906040519060208201928352604082015230606082015246608082015260808152612db160a0826112be565b805f52600c60205260405f209081546001600160401b038116906001600160401b03821615612f4d57604081901c60ff166115ac5760481c60ff16611598576001600160401b0381164210612f27575050805460ff60401b1916600160401b179055565b63c504f34d60e01b5f526004919091526001600160401b0316602452504260445260645ffd5b82633e426d5160e21b5f5260045260245ffd5b91908110156112515760051b0190565b356126cc816104f9565b91908110156112515760051b81013590601e19813603018212156104b65701908135916001600160401b0383116104b65760200182360381136104b6579190565b929192612fc782612022565b91612fd560405193846112be565b8294818452818301116104b6578281602093845f960137010152565b5f5490949192919061300b906001600160a01b0316610e6f565b331480613162575b8061315a575b613146576003549381830361311557848310801561313d575b6131245761305160045480975f5160206141d65f395f51905f52614027565b925f945f5b8781106130775750505050505050506130726112ee9160010190565b600455565b61308a613085828585612f60565b612f70565b966001600160a01b03908116908816111561311557866130c7610ac16130c08360018060a01b03165f52600260205260405f2090565b5460ff1690565b6130fa576130ed610ac16130e66130df858a8a612f7a565b3691612fbb565b89846140a8565b6130fa5750600101613056565b633b63649d60e11b5f526001600160a01b031660045260245ffd5b630da1c57360e41b5f5260045ffd5b6378f4355360e11b5f526004839052602485905260445ffd5b50848210613032565b50505050506112ee61307260045460010190565b508015613019565b508115613013565b5f54909491929190613184906001600160a01b0316610e6f565b331480613265575b8061325d575b6131465760035493818303613115578483108015613254575b613124576131ca60045480975f5160206142165f395f51905f52614027565b925f945f5b8781106131eb5750505050505050506130726112ee9160010190565b6131f9613085828585612f60565b966001600160a01b039081169088161115613115578661322f610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613247610ac16130e66130df858a8a612f7a565b6130fa57506001016131cf565b508482106131ab565b508015613192565b50811561318c565b5f54909491929190613287906001600160a01b0316610e6f565b33148061337b575b80613373575b613146576003549381830361311557848310801561336a575b613124576132e060045480977f921db041069361e63fc63658404e32c96548fc5d6a72e7fe763cb3c8b370e3fd614027565b925f945f5b8781106133015750505050505050506130726112ee9160010190565b61330f613085828585612f60565b966001600160a01b0390811690881611156131155786613345610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa5761335d610ac16130e66130df858a8a612f7a565b6130fa57506001016132e5565b508482106132ae565b508015613295565b50811561328f565b5f5490949192919061339d906001600160a01b0316610e6f565b331480613491575b80613489575b6131465760035493818303613115578483108015613480575b613124576133f660045480977fcb4f435a315262cdbbc1b22d576bc49b5e10e1516491e175d295831ff8a81305614027565b925f945f5b8781106134175750505050505050506130726112ee9160010190565b613425613085828585612f60565b966001600160a01b039081169088161115613115578661345b610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613473610ac16130e66130df858a8a612f7a565b6130fa57506001016133fb565b508482106133c4565b5080156133ab565b5081156133a5565b5f549094919291906134b3906001600160a01b0316610e6f565b331480613594575b8061358c575b6131465760035493818303613115578483108015613583575b613124576134f960045480975f5160206141965f395f51905f52614027565b925f945f5b87811061351a5750505050505050506130726112ee9160010190565b613528613085828585612f60565b966001600160a01b039081169088161115613115578661355e610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613576610ac16130e66130df858a8a612f7a565b6130fa57506001016134fe565b508482106134da565b5080156134c1565b5081156134bb565b5f549094919291906135b6906001600160a01b0316610e6f565b331480613697575b8061368f575b6131465760035493818303613115578483108015613686575b613124576135fc60045480975f5160206142365f395f51905f52614027565b925f945f5b87811061361d5750505050505050506130726112ee9160010190565b61362b613085828585612f60565b966001600160a01b0390811690881611156131155786613661610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613679610ac16130e66130df858a8a612f7a565b6130fa5750600101613601565b508482106135dd565b5080156135c4565b5081156135be565b5f549094919291906136b9906001600160a01b0316610e6f565b3314806137ad575b806137a5575b613146576003549381830361311557848310801561379c575b6131245761371260045480977f2590c13a6bfb59ce1e1dfcbf973cec418117b8426141e0cc31959b3d7bfa2d93614027565b925f945f5b8781106137335750505050505050506130726112ee9160010190565b613741613085828585612f60565b966001600160a01b0390811690881611156131155786613777610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa5761378f610ac16130e66130df858a8a612f7a565b6130fa5750600101613717565b508482106136e0565b5080156136c7565b5081156136c1565b5f549094919291906137cf906001600160a01b0316610e6f565b3314806138c3575b806138bb575b61314657600354938183036131155784831080156138b2575b6131245761382860045480977f5cdde72149ec19ce1ce0ecbedb38d9335aa5e1f8c43addf6e406b9c16e19f947614027565b925f945f5b8781106138495750505050505050506130726112ee9160010190565b613857613085828585612f60565b966001600160a01b039081169088161115613115578661388d610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa576138a5610ac16130e66130df858a8a612f7a565b6130fa575060010161382d565b508482106137f6565b5080156137dd565b5081156137d7565b5f549094919291906138e5906001600160a01b0316610e6f565b3314806139d9575b806139d1575b61314657600354938183036131155784831080156139c8575b6131245761393e60045480977f1f9aa1ad5b6acb4043f0654345360b23371878df9b7f4802b13fcb8d3fbb745f614027565b925f945f5b87811061395f5750505050505050506130726112ee9160010190565b61396d613085828585612f60565b966001600160a01b03908116908816111561311557866139a3610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa576139bb610ac16130e66130df858a8a612f7a565b6130fa5750600101613943565b5084821061390c565b5080156138f3565b5081156138ed565b5f549094919291906139fb906001600160a01b0316610e6f565b331480613aef575b80613ae7575b6131465760035493818303613115578483108015613ade575b61312457613a5460045480977f3f98d537f24f3ae50e4a30e12fbf3e5c35cf6f40f4ce125c82c1b88e3e7cf3df614027565b925f945f5b878110613a755750505050505050506130726112ee9160010190565b613a83613085828585612f60565b966001600160a01b0390811690881611156131155786613ab9610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613ad1610ac16130e66130df858a8a612f7a565b6130fa5750600101613a59565b50848210613a22565b508015613a09565b508115613a03565b5f54909491929190613b11906001600160a01b0316610e6f565b331480613c05575b80613bfd575b6131465760035493818303613115578483108015613bf4575b61312457613b6a60045480977fedb0239d3d518751089b6e176aa9d6d59832b2f29f85556f331dc42619252e62614027565b925f945f5b878110613b8b5750505050505050506130726112ee9160010190565b613b99613085828585612f60565b966001600160a01b0390811690881611156131155786613bcf610ac16130c08360018060a01b03165f52600260205260405f2090565b6130fa57613be7610ac16130e66130df858a8a612f7a565b6130fa5750600101613b6f565b50848210613b38565b508015613b1f565b508115613b19565b613c24905f5160206141965f395f51905f52612e97565b90815f52600c60205260405f2060ff815460401c166115ac575f5160206141965f395f51905f525f52600b6020527f9b6d9405e2a268edd94615fe7f07c0d5d9dda2152c2e48f4e74379972af1c618548015613cab575f5160206141b65f395f51905f526121ad5f5160206141965f395f51905f52938460016107fb6107ef8a97426121d5565b6309913ab360e31b5f5260045260245ffd5b6001600160a01b0381165f8181526002602052604090205490919060ff1615613d4d576001600160a01b0381165f908152600560205260409020541561062f57600680546001600160a01b031916831790556001600160a01b03165f90815260056020526040902054907f2c8c895ef6e3978e12490ffd8cd3b92d4717b223562f851382f5daf74f587b515f80a3565b50633b63649d60e11b5f5260045260245ffd5b6007545f5b818110613d855763dfffe2f960e01b5f526004839052602484905260445ffd5b613d9161269f82611235565b8360ff8251161480613dba575b613dab5750600101613d65565b6040015160601c949350505050565b5084602082015114613d9e565b9060405160c081018181106001600160401b0382111761129e5760405260a06005829460ff81541615158452600181015460208501526002810154604085015260038101546060850152600481015460808501520154910152565b93929190613e40613e3b865f52600d60205260405f2090565b613dc7565b94613e4e610ac18751151590565b61401557506020850180511561062f5751808203613fd9575050604084015180151580613fcf575b613f91575050606083015180151580613f87575b613f49575050608082015180151580613f3f575b613f0157505060a0015180151580613ef7575b613eb9575050565b60405163fef6c5cf60e01b81526004810191909152602481019190915260606044820152600560648201526452544d523360d81b608482015260a490fd5b5080821415613eb1565b60405163fef6c5cf60e01b815260048101919091526024810191909152606060448201526005606482015264292a26a91960d91b608482015260a490fd5b5080821415613e9e565b60405163fef6c5cf60e01b81526004810191909152602481019190915260606044820152600560648201526452544d523160d81b608482015260a490fd5b5080821415613e8a565b60405163fef6c5cf60e01b815260048101919091526024810191909152606060448201526005606482015264052544d52360dc1b608482015260a490fd5b5080821415613e76565b60405163fef6c5cf60e01b81526004808201929092526024810192909252606060448301526064820152631354951160e21b608482015260a490fd5b6350dfe91360e01b5f5260045260245ffd5b916040519160208301937f4a3d56bf3b5708e5b633d12931f9923b37fde6895d6bd92957bbfa92cd00303985526040840152606083015260808201526080815261407260a0826112be565b51902061407d612d1f565b9060405190602082019261190160f01b84526022830152604282015260428152612db16062826112be565b90915f91906001600160a01b0382161561418d5760405192600484019460248501956044860192853b1561411157509186939160209593630b135d3f60e11b8852526040845281518501809260045afa9360443d01915afa9151630b135d3f60e11b1491161690565b9796505090508151806040146141685760411461412e5750505050565b60209293955060608201515f1a835260408201516060525b5f5201516040526020600160805f825afa511860601b3d11915f606052604052565b506020929395506040820151601b8160ff1c01845260018060ff1b0316606052614146565b505050505f9056feea4a6847c3f47fe0f98dcfe2e2c074e6cb42f6d74c367b33ae8516f537e775829cc91136b2c7668ecd202c7008f17e818e108b5448a7b7fd48bd2ca6b4aab51fb40912900bb80b6bc5e38d8489266de7299eedb40b03490214410117ef53ff9279883188dbf80e171cf94b3b44b6437b838158b1d3a5df6ccc709eeb7c5217296acb9fef2a4a1ecaa044f4c8979d9f48b0d5be623c860275be31c4cbd34c169cb2d153886d95f8f2d4836fb16c9fac869e1ce9cfc93d919a0f7dfe38439b9771a2646970667358221220e0e92d56df95f5865ed5237b33c5990684fc5c337264026f0c7f338483f1599a64736f6c634300081e0033"},"sourceId":"src/CredentialManager.sol","sourcemap":"858:47851:14:-:0;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;858:47851:14;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;858:47851:14;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;12513:1;858:47851;-1:-1:-1;858:47851:14;;-1:-1:-1;;;;;;858:47851:14;17085:10;858:47851;;;;-1:-1:-1;;;;;858:47851:14;;17110:32;;17106:58;;-1:-1:-1;;;;;858:47851:14;;17178:37;;17174:63;;17247:68;858:47851;;-1:-1:-1;;;;;;858:47851:14;-1:-1:-1;;;;;858:47851:14;;;;;;;;;;;;;18522:6;;18518:59;;18591:27;;:57;;;;858:47851;18587:135;;-1:-1:-1;18752:5:14;;;;;;858:47851;;;;;19111:49;858:47851;;;;;;-1:-1:-1;858:47851:14;;;;;;19111:49;858:47851;;;;;;17393:32;858:47851;;;17393:32;858:47851;;;;;;;17435:42;858:47851;;;17435:42;858:47851;;12513:1;858:47851;-1:-1:-1;17635:3:14;858:47851;;17603:30;;;;;17684:22;;;;:::i;:::-;;858:47851;;;;;17788:32;;;17635:3;17784:67;;858:47851;;12513:1;858:47851;-1:-1:-1;858:47851:14;17866:19;858:47851;;;-1:-1:-1;858:47851:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18884:10;858:47851;;;;;;;;;;;;;;;;;;;;;;;;17923:50;12513:1;858:47851;;;;;;;;;17923:50;-1:-1:-1;;858:47851:14;;;;;;;;12513:1;858:47851;;17588:13;;858:47851;;;;-1:-1:-1;858:47851:14;17247:68;858:47851;;;-1:-1:-1;858:47851:14;17784:67;17829:22;;;-1:-1:-1;17829:22:14;858:47851;-1:-1:-1;17829:22:14;17788:32;17800:6;858:47851;17800:6;;858:47851;17800:20;17788:32;;17603:30;18052:16;858:47851;;18092:8;858:47851;;18146:8;858:47851;;18202:6;858:47851;;;;9379:25;-1:-1:-1;858:47851:14;;;;;;;;;;;;18759:3;-1:-1:-1;;;;;18791:19:14;;;;:::i;:::-;858:47851;;18828:16;;;18824:42;;858:47851;-1:-1:-1;858:47851:14;18884:10;858:47851;;;;-1:-1:-1;858:47851:14;;;18880:53;;858:47851;-1:-1:-1;858:47851:14;18884:10;858:47851;;;-1:-1:-1;858:47851:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;858:47851:14;;;;;;;;;-1:-1:-1;;;;;;858:47851:14;;;;;;19019:17;;-1:-1:-1;19019:17:14;858:47851;18737:13;;858:47851;;;;-1:-1:-1;858:47851:14;;;;;-1:-1:-1;858:47851:14;;;;;-1:-1:-1;858:47851:14;;;;;-1:-1:-1;858:47851:14;18880:53;18907:26;;;-1:-1:-1;18907:26:14;;-1:-1:-1;18907:26:14;18824:42;17151:13;;;-1:-1:-1;18853:13:14;;-1:-1:-1;18853:13:14;18587:135;18537:40;;;;;-1:-1:-1;18671:40:14;;858:47851;;;;-1:-1:-1;18671:40:14;18591:57;18622:26;;;;18591:57;;18518:59;18537:40;;;;-1:-1:-1;18537:40:14;;858:47851;-1:-1:-1;858:47851:14;;;-1:-1:-1;18537:40:14;858:47851;;;;;;;;;;;;;;-1:-1:-1;;;;;858:47851:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;858:47851:14;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;858:47851:14;;;-1:-1:-1;;;;;858:47851:14;;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;858:47851:14;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;;;858:47851:14;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o","userdoc":{"errors":{"CannotCancel()":[{"notice":"Thrown when attempting to cancel an operation that cannot be canceled (e.g., already executed)."}],"InsufficientSignatures(uint256,uint256)":[{"notice":"Thrown when the number of valid signatures provided is less than the required threshold."}],"InvalidDelay(uint256)":[{"notice":"Thrown when a timelock delay is set to 0 (invalid safety margin)."}],"InvalidEpoch(uint256,uint256)":[{"notice":"Thrown when the supplied epoch is invalid"}],"InvalidProfileConfig()":[{"notice":"Thrown when the used profile is configured incorrectly."}],"InvalidProfileId()":[{"notice":"Thrown when the used profile does not exist."}],"InvalidQuorum(uint256,uint256)":[{"notice":"Thrown when attempting to set a quorum threshold that is 0 or greater than the total operators."}],"InvalidQuoteLength()":[{"notice":"Thrown when a Quote length is invalid."}],"InvalidReportData()":[{"notice":"Thrown when a Quote ReportData does not match params."}],"InvalidVaultAddr()":[{"notice":"Thrown when a Vault address is empty (bytes32(0))."}],"InvalidVerifier()":[{"notice":"Thrown when a Quote verifier is invalid."}],"InvalidZkProof()":[{"notice":"Thrown when the ZK Proof attesting measurements is invalid."}],"MeasurementMismatch(bytes32,bytes32,string)":[{"notice":"Thrown when the measured TEE state does not match the expected state."}],"NoStrategy()":[{"notice":"Thrown when attempting to update vault admins on a chain that has no registered strategy."}],"NotOperator(address)":[{"notice":"Thrown when a signature belongs to an address that is not a registered operator."}],"ProfileInactive(uint256)":[{"notice":"Thrown when the used profile is not active."}],"SignersNotSortedOrUnique()":[{"notice":"Thrown when the provided signatures are not sorted by signer address or contain duplicates."}],"StrategyAlreadyExists()":[{"notice":"Thrown when attempting to register a strategy for a chain that already has one."}],"TimelockAlreadyCanceled(bytes32)":[{"notice":"Thrown when attempting to execute or cancel an operation that has already been canceled."}],"TimelockAlreadyExecuted(bytes32)":[{"notice":"Thrown when attempting to execute or schedule an operation that has already been executed."}],"TimelockNotReady(bytes32,uint256,uint256)":[{"notice":"Thrown when attempting to execute a timelock before the delay has elapsed."}],"TimelockUnknown(bytes32)":[{"notice":"Thrown when attempting to act on a timelock ID that does not exist or was never scheduled."}],"VaultNotFound(uint256,uint256)":[{"notice":"Thrown when a requested vault cannot be found for the specified chain."}],"ZeroAddress()":[{"notice":"Thrown when a critical configuration address (e.g., Risk Manager) is set to address(0)."}]},"events":{"AdminUpdateStrategyRegistered(uint256,uint256,address)":{"notice":"Emitted when a new cross-chain strategy is registered."},"AttestedKeyRegistered(address,bytes32)":{"notice":"Emitted when a new attested key for an operator is registered."},"DepositVaultAdministratorsUpdated(uint256,address[],uint256)":{"notice":"Emitted when the admin set of a remote vault is updated."},"DepositVaultAdministratorsUpdated(uint256,uint256,address[],uint256)":{"notice":"Emitted when a new cross-chain strategy is registered."},"LeaderUpdated(address,bytes32)":{"notice":"Emitted when the quorum leader is updated."},"MeasurementsUpdated(bytes32,bytes32)":{"notice":"Emitted when the measurements are updated."},"OperatorAdded(address)":{"notice":"Emitted when a new operator is added during initialization."},"QuorumThresholdUpdated(uint256,uint256)":{"notice":"Emitted when the signature threshold is updated."},"VaultAdded(uint256,uint256,bytes32,(uint64,uint8,uint8,uint8,uint8))":{"notice":"Emitted when a new vault is added to the registry."}},"kind":"user","methods":{"addVault(uint8,uint256,bytes32,(uint64,uint8,uint8,uint8,uint8),address[],bytes[])":{"notice":"Registers a new deposit vault to the system."},"admin()":{"notice":"TEMP Admin path, to be revised later."},"adminUpdateStrategies(uint256,uint256)":{"notice":"Maps a RoutingID to the VMID to the Strategy Contract responsible for sending messages to it."},"appointLeader(address,address[],bytes[])":{"notice":"Manually appoints a leader. Used for bootstrapping or emergency recovery."},"cancelTimelock(bytes32,address[],bytes[])":{"notice":"Cancels a pending timelocked operation."},"constructor":{"notice":"Initializes the Credential Manager with the initial operator set and configuration."},"domainSeparator()":{"notice":"Returns the EIP-712 domain separator used for verifying governance signatures."},"epoch()":{"notice":"Tracks the logical era of the TEE state to prevent replay attacks."},"executeRegistryContract(address)":{"notice":"Executes a pending Registry Contract update if the timelock has expired."},"executeRiskManager(address)":{"notice":"Executes a pending Risk Manager update if the timelock has expired."},"executeUpdateAutomataVerifier(address)":{"notice":"Sxecudes a timelocked update for the Automata Verifier address."},"getCouncilConfig()":{"notice":"Returns the full Council configuration."},"getLeader()":{"notice":"Returns the current Leader's Operator Address and Attested Key."},"getVaults(uint16,uint16)":{"notice":"Returns a paginated list of registered vaults."},"governanceNonce()":{"notice":"A monotonically increasing nonce for governance actions."},"initiateRestart()":{"notice":"Step 1: Initiates the gathering window if the system is down."},"isOperator(address)":{"notice":"Lookup to check if an address is an operator."},"latestCheckpointHash()":{"notice":"The hash of the system state (inventory) associated with the current epoch."},"leader()":{"notice":"The current active leader (Operator Address)."},"measurementProfiles(uint256)":{"notice":"The current \"Gold Image\" measurements required for valid Quotes. Matches based on profile."},"operatorToAttestedKey(address)":{"notice":"Maps Operator (EOA) -> Attested Key (TEE Address)."},"operators(uint256)":{"notice":"The list of authorized Clearing Engine operator addresses (EOAs)."},"quorumThreshold()":{"notice":"The minimum number of signatures required to execute a governance action."},"registerAdminUpdateStrategy(uint8,uint256,address,address[],bytes[])":{"notice":"Registers a strategy contract to handle updates for a specific chain."},"registerAttestedKey(bytes32)":{"notice":"Allows an operator to register their TEE's attested key."},"registryContract()":{"notice":"The address of the global Registry Contract used for asset/settler configurations."},"resolveRestart()":{"notice":"Step 3: Finalizes the restart after the window closes."},"riskManager()":{"notice":"The address of the Risk Manager (or multisig) authorized to adjust risk parameters."},"scheduleManageProfile(uint256,(bool,bytes32,bytes32,bytes32,bytes32,bytes32),address[],bytes[])":{"notice":"Governance proposes adding or updating a measurement profile (e.g., for Phala or GCP)."},"scheduleRegistryContract(address,address[],bytes[])":{"notice":"Schedules a timelocked update for the Registry Contract address."},"scheduleRiskManager(address,address[],bytes[])":{"notice":"Schedules a timelocked update for the Risk Manager address."},"scheduleUpdateAutomataVerifier(address,address[],bytes[])":{"notice":"Schedules a timelocked update for the Automata Verifier."},"setDepositVaultAdministrators(uint256,uint256,address[],uint256,address[],bytes[])":{"notice":"Updates the administrators or withdrawal quorum for a vault on a remote chain."},"submitRestartProof(uint256,bytes,bytes,address,bytes32)":{"notice":"Restarts the system using a Trustless ZK Proof (Automata / SP1). The contract stores the \"Best\" candidate."},"timelockDelayFor(bytes32)":{"notice":"Configuration mapping for how long specific operations must be delayed."},"timelockOps(bytes32)":{"notice":"Stores the status of individual scheduled operations by their hash ID."},"updateQuorumThreshold(uint256,address[],bytes[])":{"notice":"Updates the number of signatures required for valid governance actions."},"vaults(uint256)":{"notice":"The registry of all authorized Deposit Vaults."},"withdraw(address,address[],bytes[])":{"notice":"Withdraw funds held by this contract."}},"notice":"The centralized Root of Trust for the TEE Clearing Engine.","version":1}},"DepositVault":{"abi":[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_credentialManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EmptyOrders","type":"error"},{"inputs":[],"name":"Expired","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"InsufficientAdministrators","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"InsufficientAmountFromExecutor","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"given","type":"uint256"}],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"provided","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"MissedQuorum","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotCredentialManager","type":"error"},{"inputs":[],"name":"NotExecutor","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"TooSoon","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroWithdrawalQuorum","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"},{"indexed":false,"internalType":"uint256","name":"numAdminsAfter","type":"uint256"}],"name":"AdminAdded","type":"event"},{"anonymous":false,"inputs":[],"name":"AdministratorSetReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldCredentialManager","type":"address"},{"indexed":false,"internalType":"address","name":"newCredentialManager","type":"address"}],"name":"CredentialManagerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"account","type":"uint64"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"account","type":"uint64"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"Settled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"current","type":"uint256"}],"name":"WithdrawalQuorumChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":true,"internalType":"uint64","name":"account","type":"uint64"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrew","type":"event"},{"inputs":[{"internalType":"bytes32","name":"settler","type":"bytes32"},{"internalType":"address","name":"executor","type":"address"}],"name":"addSettlerExecutor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"administrators","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"approvedSettlers","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"canDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"credentialManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"credentialManagerChangeDelayBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"uint64","name":"account","type":"uint64"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"depositCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct DepositVault.Settlement","name":"order","type":"tuple"},{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"uint64","name":"account","type":"uint64"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"executeAtomicSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getApprovedSettlers","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAdministrator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastSignatureUse","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ownerWithdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pendingSettlements","outputs":[{"components":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct DepositVault.Settlement","name":"settlement","type":"tuple"},{"internalType":"address","name":"target","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct DepositVault.Settlement","name":"settlement","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct DepositVault.SignedSettlement[]","name":"orders","type":"tuple[]"},{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"uint64","name":"account","type":"uint64"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"validUntil","type":"uint256"}],"name":"pullBatchSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"uint64","name":"account","type":"uint64"}],"name":"pushBatchSettlements","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"settler","type":"bytes32"}],"name":"removeSettler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"newAdministrators","type":"address[]"},{"internalType":"uint256","name":"newWithdrawalQuorum","type":"uint256"}],"name":"setAdministrators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCredentialManager","type":"address"}],"name":"setCredentialManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setDepositorStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"}],"name":"setDomainSeparator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"settlementCaps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"settlementCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct DepositVault.Withdrawal","name":"withdrawal","type":"tuple"},{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"uint64","name":"account","type":"uint64"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"bytes32","name":"epochHash","type":"bytes32"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"withdrawalCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"contractName":"DepositVault","deploymentBytecode":{"bytecode":"0x60803460ad57601f611d9c38819003918201601f19168301916001600160401b0383118484101760b157808492604094855283398101031260ad57604b602060458360c5565b920160c5565b6138406006556001600160a01b03909116908115609e576001600160a01b0316908115609e5760018060a01b03195f5416175f5560018060a01b03196001541617600155604051611cc390816100d98239f35b63d92e233d60e01b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820360ad5756fe60806040526004361015610011575f80fd5b5f3560e01c80630a2eb301146117d75780630b9b17a61461162357806313af4035146115d85780631f7b44831461159357806321e6652c146114e6578063224b93e11461148a57806323c5673114611228578063267f84cc14610f845780632b0c1a1e14610f5c5780633684f4ac14610eb05780633a87fe4d14610e7857806341774bfe14610d255780634bf0d33114610ce85780635fe53eca146109c75780637438b9371461099657806375538ec61461083a5780638da5cb5b146108135780638dff2305146107ce57806392698ac61461071857806393ea8a7d146106fb578063987b71ce146106b657806398af97721461067e578063a33c9d0014610661578063ad9fa8bc1461053c578063d89d1510146104fa578063d8c8785d146104dd578063e4402369146101b35763f585b64f1461014d575f80fd5b346101a05760603660031901126101a057610166611804565b61016e61181a565b5f549091906001600160a01b031633036101a4576001600160a01b038216156101a05761019e9160443591611bc6565b005b5f80fd5b6330cd747160e01b5f5260045ffd5b346101a05760a03660031901126101a0576004356001600160401b0381116101a0576101e390369060040161185a565b90602435604435916001600160401b0383168093036101a0576064356001600160a01b03811691908281036101a057608435908142116104ce57845f52600960205260405f20865f5260205260405f20546101a057610241336119c8565b156104bf57845f52600a60205260405f20865f5260205260405f2054936002549488156104b0575f5b898110610298578989895f52600a60205260405f20905f5260205261029460405f20918254611a11565b9055005b6102a3818b88611b31565b9160808301359080820361049b57508291908989838e8e8b866bffffffffffffffffffffffff196102d38b611a4a565b60601b169260208b013597889760408d019d8e6001600160601b0319906102f990611a4a565b60601b1690606001359961030e978b93611a5e565b8051906020012091610320918d611b31565b60a0810161032d91611aeb565b9061033792611bb1565b6001830180841161048757958c5f5260096020528d60405f20905f5260205260405f209360405192610368846118e4565b60a0883603126101a05761039860405193610382856118ff565b61038b8a611830565b8552866020860152611830565b604084015260608301526080820152815260208101928784528054600160401b811015610473576103ce916001820181556118b7565b939093610460579051805184546001600160a01b03199081166001600160a01b03928316178655602083015160018781019190915560408401516002880180548416918516919091179055606084015160038801556080939093015160048701559251600590950180549093169416939093179055909261045a9190879061045590611a4a565b611bc6565b0161026a565b634e487b7160e01b5f525f60045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b6306427aeb60e01b5f5260045260245260445ffd5b63164bb4b560e11b5f5260045ffd5b637bfa4b9f60e01b5f5260045ffd5b630407b05b60e31b5f5260045ffd5b346101a0575f3660031901126101a0576020600f54604051908152f35b346101a05760203660031901126101a057600435600d548110156101a057610523602091611983565b905460405160039290921b1c6001600160a01b03168152f35b346101a05760403660031901126101a05760043561055861181a565b5f549091906001600160a01b031633036101a457805f52600760205260ff60405f2054161561060a575b5f52600360205260405f2090600182019160018060a01b0382165f528260205260ff60405f205416156105b157005b8054600160401b811015610473576105ce916001820181556119b3565b81546001600160a01b0393841660039290921b82811b94901b19169290921790555f90815260209190915260409020805460ff19166001179055005b600454600160401b8110156104735761064361062d82600185940160045561199b565b819391549060031b91821b915f19901b19161790565b9055805f52600760205260405f20600160ff19825416179055610582565b346101a0575f3660031901126101a0576020600654604051908152f35b346101a05760203660031901126101a0576001600160a01b0361069f611804565b165f526008602052602060405f2054604051908152f35b346101a05760403660031901126101a0576106cf611844565b6004355f52600b6020526001600160401b0360405f2091165f52602052602060405f2054604051908152f35b346101a0575f3660031901126101a0576020600554604051908152f35b346101a0575f3660031901126101a0576040518060206004549283815201809260045f527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b905f5b8181106107b8575050508161077691038261191a565b604051918291602083019060208452518091526040830191905f5b81811061079f575050500390f35b8251845285945060209384019390920191600101610791565b8254845260209093019260019283019201610760565b346101a05760403660031901126101a0576107e7611844565b6004355f52600a6020526001600160401b0360405f2091165f52602052602060405f2054604051908152f35b346101a0575f3660031901126101a0575f546040516001600160a01b039091168152602090f35b346101a05760803660031901126101a057600435610856611844565b906044356001600160a01b03811681036101a05760643590335f52600e60205260ff60405f205416156109645781156109395761089582303384611b53565b825f52600b60205260405f206001600160401b0385165f52602052827fe2a2bdf36e2c262c44c94cde71107e3d083338d05880f1d98e34aef60a57732361090760405f2054946040519182916001600160401b038a16968360209093929193604081019460018060a01b031681520152565b0390a45f52600b6020526001600160401b0360405f2091165f5260205260405f20805490600182018092116104875755005b606460405162461bcd60e51b81526020600482015260046024820152635a65726f60e01b6044820152fd5b60405162461bcd60e51b815260206004820152600a60248201526910b232b837b9b4ba37b960b11b6044820152606490fd5b346101a05760203660031901126101a0575f546001600160a01b031633036101a4576002546101a057600435600255005b346101a057366003190161012081126101a0576060136101a057606435608435906001600160401b0382168092036101a05760a435906001600160a01b03821682036101a05760c43592610104356001600160401b0381116101a057610a3190369060040161185a565b929093600554958042116104ce57868510610cd157825f52600c60205260405f20845f5260205260405f20549660443597808903610cba5750610a7386611ad4565b96610a81604051988961191a565b868852601f19610a9088611ad4565b013660208a01375f906002546001600160601b0319610aad611a1e565b60601b16602435956040519160208301937f797aea45f9ae7a23c83a831da6478b151bf9c36a60c32d897309fb02a25102ba8552604084015260608301528660808301528860a08301528c60c083015260e082015260e4356101008201526001600160601b03198760601b166101208201526101208152610b306101408261191a565b519020905f5b89811015610caa57610b57610b508260051b840184611aeb565b9085611c17565b6001600160a01b038116908115610c9b57610b71906119c8565b15610c9b5760015f828e5b888310610c6b575b505050610c4b575b50848414610b9c57600101610b36565b50505091939550919395505b818110610c36575050825f52600c60205260405f20845f5260205260405f2080549060018201809211610487577f014b9c5afdefb51fefc3d39536fa7cd9723837d5a8b663cd7fd19ebd127987c793610c0a9284925543600f55610455611a1e565b610c12611a1e565b604080516001600160a01b039092168252602082019290925290819081015b0390a4005b6326a15da760e01b5f5260045260245260445ffd5b610c58858d969396611b1d565b525f19811461048757600101928c610b8c565b6001600160a01b0390610c7f908490611b1d565b511614610c9057600101828e610b7c565b50505f8e828e610b84565b638baa579f60e01b5f5260045ffd5b5050509193955091939550610ba8565b88906306427aeb60e01b5f5260045260245260445ffd5b86856326a15da760e01b5f5260045260245260445ffd5b346101a05760203660031901126101a0576001600160a01b03610d09611804565b165f52600e602052602060ff60405f2054166040519015158152f35b346101a05760203660031901126101a0575f54600435906001600160a01b031633036101a4576004545f828152600760205260408120805460ff191690555b818110610def575b50505f52600360205260405f205f60018201905b8254811015610dc35780610d96600192856119b3565b838060a01b0391549060031b1c16828060a01b03165f528260205260405f2060ff19815416905501610d80565b82545f84558381610dd057005b5f5260205f20908101905b818110610de457005b5f8155600101610ddb565b82610df98261199b565b90549060031b1c14610e0d57600101610d64565b905f1981019081116104875761062d610e28610e359261199b565b90549060031b1c9261199b565b90556004548015610e64575f1901610e4c8161199b565b8154905f199060031b1b191690556004558180610d6c565b634e487b7160e01b5f52603160045260245ffd5b346101a05760203660031901126101a0576004356004548110156101a057610ea160209161199b565b90549060031b1c604051908152f35b346101a05760603660031901126101a057610ec9611844565b604435906004355f5260096020526001600160401b0360405f2091165f5260205260405f2080548210156101a05760c091610f03916118b7565b50610f0d8161193b565b6005909101546040805183516001600160a01b039081168252602080860151908301528285015181169282019290925260608085015190820152608093840151938101939093521660a0820152f35b346101a0575f3660031901126101a0576001546040516001600160a01b039091168152602090f35b346101a057366003190161014081126101a05760a0136101a05760a43560c4356001600160401b0381168091036101a05760e43591610104356001600160401b0381116101a057610fd990369060040161188a565b93610124356001600160401b0381116101a057610ffa90369060040161188a565b9590928242116104ce575f85815260036020908152604080832033845260010190915290205460ff161561121957845f52600a60205260405f20865f5260205260405f20549660843597808903610cba57506110a190600254956110956001600160601b0319611068611a1e565b60601b16968b8b8b6024359b6001600160601b0319611085611a34565b60601b168d6064359d8e93611a5e565b60208151910120611bb1565b43600f55845f52600a60205260405f20865f5260205260405f2090815460018101809111610487576020925560846110d7611a1e565b846040519586948593631f8eac2760e11b855260018060a01b0316600485015289602485015260606044850152816064850152848401375f838284010152601f801991011681010301815f335af190811561120e575f916111dc575b508181106111c757906111737ff2401a17cb3d1986de3a662a21d4c56a1bcc296682786f78d69805a49be0ba3c939261116a611a34565b30903390611b53565b6111808233610455611a1e565b610c3161118b611a1e565b91611194611a34565b604080516001600160a01b0395861681526020810196909652931692840192909252606083019190915281906080820190565b63d44c3d9d60e01b5f5260045260245260445ffd5b90506020813d602011611206575b816111f76020938361191a565b810103126101a0575186611133565b3d91506111ea565b6040513d5f823e3d90fd5b6361968ebb60e11b5f5260045ffd5b346101a05760403660031901126101a0576004356001600160401b0381116101a05761125890369060040161185a565b600154909190602435906001600160a01b0316330361147b576001811061146c57808310611456575f5b838110156112be576001600160a01b036112a1600583901b8501611a4a565b16156112af57600101611282565b63d92e233d60e01b5f5260045ffd5b5091906001600160401b03821161047357600160401b821161047357600d5482600d55808310611412575b50600d5f525f5b8281106113d757837f74e3f7a222a002bb0346144c8442604f86b79a5319301c8b2393dbe33ba3f1ec5f80a1600d545f5b81811061136c5782600554908060055580820361133a57005b7f71847092dda23e5394806b377214ca90449cdd1413463150e7f577ccefea54d89160409182519182526020820152a1005b61137581611983565b905460018301929160031b1c6001600160a01b031682821161048757604080516001600160a01b0392909216825260208201939093526001927f723c2b747529ca7f5eb53a74808f4a8b9bf264f0fc450fd904900151da74548a91a101611321565b60019060206113e584611a4a565b930192817fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50155016112f0565b600d5f527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb59081019083015b81811061144b57506112e9565b5f815560010161143e565b82633e1a6b7d60e21b5f5260045260245260445ffd5b6345f8facb60e11b5f5260045ffd5b6326b672e560e01b5f5260045ffd5b346101a05760403660031901126101a0576114a3611804565b602435908115158092036101a0575f546001600160a01b031633036101a45760018060a01b03165f52600e60205260405f209060ff801983541691161790555f80f35b346101a05760203660031901126101a0576114ff611804565b5f546001600160a01b031633036101a4576001600160a01b031680156112af5761152e600f5460065490611a11565b4310156115845760407feb63fb900cbf0301de00619a02ae3f5996820dabc03207c0e0d97046e521d7b99160015490806001600160601b0360a01b83161760015582519160018060a01b031682526020820152a1005b636fed7d8560e01b5f5260045ffd5b346101a05760403660031901126101a0576115ac611844565b6004355f52600c6020526001600160401b0360405f2091165f52602052602060405f2054604051908152f35b346101a05760203660031901126101a0576115f1611804565b5f54906001600160a01b03821633036101a4576001600160a01b03169081156112af576001600160a01b031916175f55005b346101a05760403660031901126101a05760043561163f611844565b611648336119c8565b156104bf576001600160401b0316905f5b815f52600960205260405f20835f5260205260405f205463ffffffff821610156117685763ffffffff90825f52600960205260405f20845f526020526116a28160405f206118b7565b506116eb604051916116b3836118e4565b6116bc8161193b565b8084526005909101546001600160a01b0390811660208501819052604083015160609093015192309216611b53565b51608080820151825160208085015160408087015160609788015182516001600160a01b0396871681529485019390935293909316928201929092529384015291869186917ff2401a17cb3d1986de3a662a21d4c56a1bcc296682786f78d69805a49be0ba3c9190a41663ffffffff811461048757600101611659565b505f52600960205260405f20905f5260205260405f208054905f81558161178b57005b81600602916006830403610487575f5260205f20908101905b8181106117ad57005b805f600692555f60018201555f60028201555f60038201555f60048201555f6005820155016117a4565b346101a05760203660031901126101a05760206117fa6117f5611804565b6119c8565b6040519015158152f35b600435906001600160a01b03821682036101a057565b602435906001600160a01b03821682036101a057565b35906001600160a01b03821682036101a057565b602435906001600160401b03821682036101a057565b9181601f840112156101a0578235916001600160401b0383116101a0576020808501948460051b0101116101a057565b9181601f840112156101a0578235916001600160401b0383116101a057602083818601950101116101a057565b80548210156118d0575f52600660205f20910201905f90565b634e487b7160e01b5f52603260045260245ffd5b604081019081106001600160401b0382111761047357604052565b60a081019081106001600160401b0382111761047357604052565b90601f801991011681019081106001600160401b0382111761047357604052565b90604051611948816118ff565b82546001600160a01b039081168252600184015460208301526002840154166040820152600383015460608201526004909201546080830152565b600d548110156118d057600d5f5260205f2001905f90565b6004548110156118d05760045f5260205f2001905f90565b80548210156118d0575f5260205f2001905f90565b600d54905f5b8281106119dc575050505f90565b6119e581611983565b905460039190911b1c6001600160a01b0390811690831614611a09576001016119ce565b505050600190565b9190820180921161048757565b6004356001600160a01b03811681036101a05790565b6044356001600160a01b03811681036101a05790565b356001600160a01b03811681036101a05790565b989796959493929190604051997fd5bba88286cccde9162e20a797ff293aac0b11190037e71286b8a5271985e4cb60208c015260408b015260608a0152608089015260a088015260c087015260e08601526101008501526101208401526101408301526101408252611ad26101608361191a565b565b6001600160401b0381116104735760051b60200190565b903590601e19813603018212156101a057018035906001600160401b0382116101a0576020019181360383136101a057565b80518210156118d05760209160051b010190565b91908110156118d05760051b8101359060be19813603018212156101a0570190565b916040519360605260405260601b602c526323b872dd60601b600c5260205f6064601c82855af1908160015f51141615611b93575b50505f606052604052565b3b153d171015611ba4575f80611b88565b637939f4245f526004601cfd5b916117f591611bbf93611c17565b15610c9b57565b919060145260345263a9059cbb60601b5f5260205f6044601082855af1908160015f51141615611bf9575b50505f603452565b3b153d171015611c0a575f80611bf1565b6390b8ec185f526004601cfd5b604080515f95949093918114611c6257604114611c3357505050565b604080929395508101355f1a60205281375b5f526020604060805f60015afa505f6060523d6060185191604052565b5060208082013560ff81901c601b0190915290356040526001600160ff1b0316606052909250611c4556fea2646970667358221220759248af50aaddb85c7923e0a741f511253ffd21881e408db3f18ad98ccafffb64736f6c634300081e0033"},"devdoc":{"kind":"dev","methods":{"addSettlerExecutor(bytes32,address)":{"details":"Reverts with `NotOwner`; Only the admin can set the settler executor.","params":{"executor":": The settler's assigned executor address.","settler":": The settler's tplus account key."}},"constructor":{"details":"Reverts with `ZeroAddress()` if `_owner` is null.Reverts with `ZeroAddress()` if `_credentialManager` is null.","params":{"_credentialManager":"The address of the credential manager.","_owner":"The address to set as the owner."}},"deposit(bytes32,uint64,address,uint256)":{"details":"Reverts if the amount is 0.","params":{"account":": The account index of the specified user that will be credited with the deposit","amount":": The amount of the token to deposit.","tokenAddress":": The address of the token to deposit.","user":": The user whose account will be credited with the deposit."}},"executeAtomicSettlement((address,uint256,address,uint256,uint256),bytes32,uint64,uint256,bytes,bytes)":{"details":"Reverts with `Expired` if the block timestamp is greater than `validUntil`.Reverts with `NotExecutor`; Only the executor can settle.Reverts with `InvalidNonce` if the nonce has already been used.Reverts with `SignatureError` if the signer is not an admin.Reverts with `InsufficientAmountFromExecutor` if the `order.amountIn` is less than what the executor reports","params":{"account":": The account index of the t+ user that will be used for settlement","data":": The data to execute as part of settlement callback.","order":": The settlement order.","signature":": The signature from the t+ clearing engine.","user":": The t+ user who is executing the settlement.","validUntil":": How long until the signature expires."}},"getApprovedSettlers()":{"returns":{"_0":"An array of addresses (as bytes32) that are currently approved settlers."}},"pullBatchSettlement(((address,uint256,address,uint256,uint256),bytes)[],bytes32,uint64,address,uint256)":{"details":"Reverts with `Expired` if the block timestamp is greater than `validUntil`.Reverts if a batch settlement has already started.Reverts with `NotAdmin`; Only an admin can execute the settlement.Reverts with `InvalidNonce` if the nonce has already been used.Reverts with `SignatureError` if the signer is not an admin.","params":{"orders":": The settlement orders.","target":": The target address to send the token to, pull tokens from, and execute callback on.","user":": The t+ user who is executing the settlement.","validUntil":": The timestamp when the settlement signature expires."}},"pushBatchSettlements(bytes32,uint64)":{"details":"Reverts with `NotAdmin`; Only an admin can execute the settlement.","params":{"account":": The account of the t+ user to execute settlement against","user":": The t+ user who is executing the settlement."}},"removeSettler(bytes32)":{"details":"Reverts with `NotOwner`; Only the admin can remove a settler.","params":{"settler":": The settler's tplus account key."}},"setDomainSeparator(bytes32)":{"details":"Reverts with `NotOwner`; Only the admin can set the domain separator.","params":{"domainSeparator":": The value to set."}},"setOwner(address)":{"details":"Reverts with `NotOwner`; Only the owner can set a new owner."},"withdraw((address,uint256,uint256),bytes32,uint64,address,uint256,bytes32,bytes[])":{"details":"Reverts with `Expired` if the block timestamp is greater than `validUntil`.Reverts with `InvalidNonce` if the nonce has already been used.Reverts with `SignatureError` if the signer is not an admin.","params":{"account":": The account of the t+ user that will be debited by the withdrawal.","signatures":": t+ clearing engine signatures.","target":": The target address to send the token to.","user":": The user whose account will be debited by the withdrawal.","validUntil":": The timestamp when the withdrawal signature expires.","withdrawal":": The withdrawal token and amount."}}},"stateVariables":{"credentialManager":{"details":"In production, this will be an upgradeable proxy"},"owner":{"details":"Should be set to the DStack container shared secret address."},"settlementCaps":{"details":"Currently unused \u2014 implementation pending design finalization."}},"version":1},"methodIdentifiers":{"addSettlerExecutor(bytes32,address)":"0xad9fa8bc","administrators(uint256)":"0xd89d1510","approvedSettlers(uint256)":"0x3a87fe4d","canDeposit(address)":"0x4bf0d331","credentialManager()":"0x2b0c1a1e","credentialManagerChangeDelayBlocks()":"0xa33c9d00","deposit(bytes32,uint64,address,uint256)":"0x75538ec6","depositCounts(bytes32,uint64)":"0x987b71ce","executeAtomicSettlement((address,uint256,address,uint256,uint256),bytes32,uint64,uint256,bytes,bytes)":"0x267f84cc","getApprovedSettlers()":"0x92698ac6","isAdministrator(address)":"0x0a2eb301","lastSignatureUse()":"0xd8c8785d","owner()":"0x8da5cb5b","ownerWithdrawToken(address,address,uint256)":"0xf585b64f","pendingSettlements(bytes32,uint64,uint256)":"0x3684f4ac","pullBatchSettlement(((address,uint256,address,uint256,uint256),bytes)[],bytes32,uint64,address,uint256)":"0xe4402369","pushBatchSettlements(bytes32,uint64)":"0x0b9b17a6","removeSettler(bytes32)":"0x41774bfe","setAdministrators(address[],uint256)":"0x23c56731","setCredentialManager(address)":"0x21e6652c","setDepositorStatus(address,bool)":"0x224b93e1","setDomainSeparator(bytes32)":"0x7438b937","setOwner(address)":"0x13af4035","settlementCaps(address)":"0x98af9772","settlementCounts(bytes32,uint64)":"0x8dff2305","withdraw((address,uint256,uint256),bytes32,uint64,address,uint256,bytes32,bytes[])":"0x5fe53eca","withdrawalCounts(bytes32,uint64)":"0x1f7b4483","withdrawalQuorum()":"0x93ea8a7d"},"runtimeBytecode":{"bytecode":"0x60806040526004361015610011575f80fd5b5f3560e01c80630a2eb301146117d75780630b9b17a61461162357806313af4035146115d85780631f7b44831461159357806321e6652c146114e6578063224b93e11461148a57806323c5673114611228578063267f84cc14610f845780632b0c1a1e14610f5c5780633684f4ac14610eb05780633a87fe4d14610e7857806341774bfe14610d255780634bf0d33114610ce85780635fe53eca146109c75780637438b9371461099657806375538ec61461083a5780638da5cb5b146108135780638dff2305146107ce57806392698ac61461071857806393ea8a7d146106fb578063987b71ce146106b657806398af97721461067e578063a33c9d0014610661578063ad9fa8bc1461053c578063d89d1510146104fa578063d8c8785d146104dd578063e4402369146101b35763f585b64f1461014d575f80fd5b346101a05760603660031901126101a057610166611804565b61016e61181a565b5f549091906001600160a01b031633036101a4576001600160a01b038216156101a05761019e9160443591611bc6565b005b5f80fd5b6330cd747160e01b5f5260045ffd5b346101a05760a03660031901126101a0576004356001600160401b0381116101a0576101e390369060040161185a565b90602435604435916001600160401b0383168093036101a0576064356001600160a01b03811691908281036101a057608435908142116104ce57845f52600960205260405f20865f5260205260405f20546101a057610241336119c8565b156104bf57845f52600a60205260405f20865f5260205260405f2054936002549488156104b0575f5b898110610298578989895f52600a60205260405f20905f5260205261029460405f20918254611a11565b9055005b6102a3818b88611b31565b9160808301359080820361049b57508291908989838e8e8b866bffffffffffffffffffffffff196102d38b611a4a565b60601b169260208b013597889760408d019d8e6001600160601b0319906102f990611a4a565b60601b1690606001359961030e978b93611a5e565b8051906020012091610320918d611b31565b60a0810161032d91611aeb565b9061033792611bb1565b6001830180841161048757958c5f5260096020528d60405f20905f5260205260405f209360405192610368846118e4565b60a0883603126101a05761039860405193610382856118ff565b61038b8a611830565b8552866020860152611830565b604084015260608301526080820152815260208101928784528054600160401b811015610473576103ce916001820181556118b7565b939093610460579051805184546001600160a01b03199081166001600160a01b03928316178655602083015160018781019190915560408401516002880180548416918516919091179055606084015160038801556080939093015160048701559251600590950180549093169416939093179055909261045a9190879061045590611a4a565b611bc6565b0161026a565b634e487b7160e01b5f525f60045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b6306427aeb60e01b5f5260045260245260445ffd5b63164bb4b560e11b5f5260045ffd5b637bfa4b9f60e01b5f5260045ffd5b630407b05b60e31b5f5260045ffd5b346101a0575f3660031901126101a0576020600f54604051908152f35b346101a05760203660031901126101a057600435600d548110156101a057610523602091611983565b905460405160039290921b1c6001600160a01b03168152f35b346101a05760403660031901126101a05760043561055861181a565b5f549091906001600160a01b031633036101a457805f52600760205260ff60405f2054161561060a575b5f52600360205260405f2090600182019160018060a01b0382165f528260205260ff60405f205416156105b157005b8054600160401b811015610473576105ce916001820181556119b3565b81546001600160a01b0393841660039290921b82811b94901b19169290921790555f90815260209190915260409020805460ff19166001179055005b600454600160401b8110156104735761064361062d82600185940160045561199b565b819391549060031b91821b915f19901b19161790565b9055805f52600760205260405f20600160ff19825416179055610582565b346101a0575f3660031901126101a0576020600654604051908152f35b346101a05760203660031901126101a0576001600160a01b0361069f611804565b165f526008602052602060405f2054604051908152f35b346101a05760403660031901126101a0576106cf611844565b6004355f52600b6020526001600160401b0360405f2091165f52602052602060405f2054604051908152f35b346101a0575f3660031901126101a0576020600554604051908152f35b346101a0575f3660031901126101a0576040518060206004549283815201809260045f527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b905f5b8181106107b8575050508161077691038261191a565b604051918291602083019060208452518091526040830191905f5b81811061079f575050500390f35b8251845285945060209384019390920191600101610791565b8254845260209093019260019283019201610760565b346101a05760403660031901126101a0576107e7611844565b6004355f52600a6020526001600160401b0360405f2091165f52602052602060405f2054604051908152f35b346101a0575f3660031901126101a0575f546040516001600160a01b039091168152602090f35b346101a05760803660031901126101a057600435610856611844565b906044356001600160a01b03811681036101a05760643590335f52600e60205260ff60405f205416156109645781156109395761089582303384611b53565b825f52600b60205260405f206001600160401b0385165f52602052827fe2a2bdf36e2c262c44c94cde71107e3d083338d05880f1d98e34aef60a57732361090760405f2054946040519182916001600160401b038a16968360209093929193604081019460018060a01b031681520152565b0390a45f52600b6020526001600160401b0360405f2091165f5260205260405f20805490600182018092116104875755005b606460405162461bcd60e51b81526020600482015260046024820152635a65726f60e01b6044820152fd5b60405162461bcd60e51b815260206004820152600a60248201526910b232b837b9b4ba37b960b11b6044820152606490fd5b346101a05760203660031901126101a0575f546001600160a01b031633036101a4576002546101a057600435600255005b346101a057366003190161012081126101a0576060136101a057606435608435906001600160401b0382168092036101a05760a435906001600160a01b03821682036101a05760c43592610104356001600160401b0381116101a057610a3190369060040161185a565b929093600554958042116104ce57868510610cd157825f52600c60205260405f20845f5260205260405f20549660443597808903610cba5750610a7386611ad4565b96610a81604051988961191a565b868852601f19610a9088611ad4565b013660208a01375f906002546001600160601b0319610aad611a1e565b60601b16602435956040519160208301937f797aea45f9ae7a23c83a831da6478b151bf9c36a60c32d897309fb02a25102ba8552604084015260608301528660808301528860a08301528c60c083015260e082015260e4356101008201526001600160601b03198760601b166101208201526101208152610b306101408261191a565b519020905f5b89811015610caa57610b57610b508260051b840184611aeb565b9085611c17565b6001600160a01b038116908115610c9b57610b71906119c8565b15610c9b5760015f828e5b888310610c6b575b505050610c4b575b50848414610b9c57600101610b36565b50505091939550919395505b818110610c36575050825f52600c60205260405f20845f5260205260405f2080549060018201809211610487577f014b9c5afdefb51fefc3d39536fa7cd9723837d5a8b663cd7fd19ebd127987c793610c0a9284925543600f55610455611a1e565b610c12611a1e565b604080516001600160a01b039092168252602082019290925290819081015b0390a4005b6326a15da760e01b5f5260045260245260445ffd5b610c58858d969396611b1d565b525f19811461048757600101928c610b8c565b6001600160a01b0390610c7f908490611b1d565b511614610c9057600101828e610b7c565b50505f8e828e610b84565b638baa579f60e01b5f5260045ffd5b5050509193955091939550610ba8565b88906306427aeb60e01b5f5260045260245260445ffd5b86856326a15da760e01b5f5260045260245260445ffd5b346101a05760203660031901126101a0576001600160a01b03610d09611804565b165f52600e602052602060ff60405f2054166040519015158152f35b346101a05760203660031901126101a0575f54600435906001600160a01b031633036101a4576004545f828152600760205260408120805460ff191690555b818110610def575b50505f52600360205260405f205f60018201905b8254811015610dc35780610d96600192856119b3565b838060a01b0391549060031b1c16828060a01b03165f528260205260405f2060ff19815416905501610d80565b82545f84558381610dd057005b5f5260205f20908101905b818110610de457005b5f8155600101610ddb565b82610df98261199b565b90549060031b1c14610e0d57600101610d64565b905f1981019081116104875761062d610e28610e359261199b565b90549060031b1c9261199b565b90556004548015610e64575f1901610e4c8161199b565b8154905f199060031b1b191690556004558180610d6c565b634e487b7160e01b5f52603160045260245ffd5b346101a05760203660031901126101a0576004356004548110156101a057610ea160209161199b565b90549060031b1c604051908152f35b346101a05760603660031901126101a057610ec9611844565b604435906004355f5260096020526001600160401b0360405f2091165f5260205260405f2080548210156101a05760c091610f03916118b7565b50610f0d8161193b565b6005909101546040805183516001600160a01b039081168252602080860151908301528285015181169282019290925260608085015190820152608093840151938101939093521660a0820152f35b346101a0575f3660031901126101a0576001546040516001600160a01b039091168152602090f35b346101a057366003190161014081126101a05760a0136101a05760a43560c4356001600160401b0381168091036101a05760e43591610104356001600160401b0381116101a057610fd990369060040161188a565b93610124356001600160401b0381116101a057610ffa90369060040161188a565b9590928242116104ce575f85815260036020908152604080832033845260010190915290205460ff161561121957845f52600a60205260405f20865f5260205260405f20549660843597808903610cba57506110a190600254956110956001600160601b0319611068611a1e565b60601b16968b8b8b6024359b6001600160601b0319611085611a34565b60601b168d6064359d8e93611a5e565b60208151910120611bb1565b43600f55845f52600a60205260405f20865f5260205260405f2090815460018101809111610487576020925560846110d7611a1e565b846040519586948593631f8eac2760e11b855260018060a01b0316600485015289602485015260606044850152816064850152848401375f838284010152601f801991011681010301815f335af190811561120e575f916111dc575b508181106111c757906111737ff2401a17cb3d1986de3a662a21d4c56a1bcc296682786f78d69805a49be0ba3c939261116a611a34565b30903390611b53565b6111808233610455611a1e565b610c3161118b611a1e565b91611194611a34565b604080516001600160a01b0395861681526020810196909652931692840192909252606083019190915281906080820190565b63d44c3d9d60e01b5f5260045260245260445ffd5b90506020813d602011611206575b816111f76020938361191a565b810103126101a0575186611133565b3d91506111ea565b6040513d5f823e3d90fd5b6361968ebb60e11b5f5260045ffd5b346101a05760403660031901126101a0576004356001600160401b0381116101a05761125890369060040161185a565b600154909190602435906001600160a01b0316330361147b576001811061146c57808310611456575f5b838110156112be576001600160a01b036112a1600583901b8501611a4a565b16156112af57600101611282565b63d92e233d60e01b5f5260045ffd5b5091906001600160401b03821161047357600160401b821161047357600d5482600d55808310611412575b50600d5f525f5b8281106113d757837f74e3f7a222a002bb0346144c8442604f86b79a5319301c8b2393dbe33ba3f1ec5f80a1600d545f5b81811061136c5782600554908060055580820361133a57005b7f71847092dda23e5394806b377214ca90449cdd1413463150e7f577ccefea54d89160409182519182526020820152a1005b61137581611983565b905460018301929160031b1c6001600160a01b031682821161048757604080516001600160a01b0392909216825260208201939093526001927f723c2b747529ca7f5eb53a74808f4a8b9bf264f0fc450fd904900151da74548a91a101611321565b60019060206113e584611a4a565b930192817fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50155016112f0565b600d5f527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb59081019083015b81811061144b57506112e9565b5f815560010161143e565b82633e1a6b7d60e21b5f5260045260245260445ffd5b6345f8facb60e11b5f5260045ffd5b6326b672e560e01b5f5260045ffd5b346101a05760403660031901126101a0576114a3611804565b602435908115158092036101a0575f546001600160a01b031633036101a45760018060a01b03165f52600e60205260405f209060ff801983541691161790555f80f35b346101a05760203660031901126101a0576114ff611804565b5f546001600160a01b031633036101a4576001600160a01b031680156112af5761152e600f5460065490611a11565b4310156115845760407feb63fb900cbf0301de00619a02ae3f5996820dabc03207c0e0d97046e521d7b99160015490806001600160601b0360a01b83161760015582519160018060a01b031682526020820152a1005b636fed7d8560e01b5f5260045ffd5b346101a05760403660031901126101a0576115ac611844565b6004355f52600c6020526001600160401b0360405f2091165f52602052602060405f2054604051908152f35b346101a05760203660031901126101a0576115f1611804565b5f54906001600160a01b03821633036101a4576001600160a01b03169081156112af576001600160a01b031916175f55005b346101a05760403660031901126101a05760043561163f611844565b611648336119c8565b156104bf576001600160401b0316905f5b815f52600960205260405f20835f5260205260405f205463ffffffff821610156117685763ffffffff90825f52600960205260405f20845f526020526116a28160405f206118b7565b506116eb604051916116b3836118e4565b6116bc8161193b565b8084526005909101546001600160a01b0390811660208501819052604083015160609093015192309216611b53565b51608080820151825160208085015160408087015160609788015182516001600160a01b0396871681529485019390935293909316928201929092529384015291869186917ff2401a17cb3d1986de3a662a21d4c56a1bcc296682786f78d69805a49be0ba3c9190a41663ffffffff811461048757600101611659565b505f52600960205260405f20905f5260205260405f208054905f81558161178b57005b81600602916006830403610487575f5260205f20908101905b8181106117ad57005b805f600692555f60018201555f60028201555f60038201555f60048201555f6005820155016117a4565b346101a05760203660031901126101a05760206117fa6117f5611804565b6119c8565b6040519015158152f35b600435906001600160a01b03821682036101a057565b602435906001600160a01b03821682036101a057565b35906001600160a01b03821682036101a057565b602435906001600160401b03821682036101a057565b9181601f840112156101a0578235916001600160401b0383116101a0576020808501948460051b0101116101a057565b9181601f840112156101a0578235916001600160401b0383116101a057602083818601950101116101a057565b80548210156118d0575f52600660205f20910201905f90565b634e487b7160e01b5f52603260045260245ffd5b604081019081106001600160401b0382111761047357604052565b60a081019081106001600160401b0382111761047357604052565b90601f801991011681019081106001600160401b0382111761047357604052565b90604051611948816118ff565b82546001600160a01b039081168252600184015460208301526002840154166040820152600383015460608201526004909201546080830152565b600d548110156118d057600d5f5260205f2001905f90565b6004548110156118d05760045f5260205f2001905f90565b80548210156118d0575f5260205f2001905f90565b600d54905f5b8281106119dc575050505f90565b6119e581611983565b905460039190911b1c6001600160a01b0390811690831614611a09576001016119ce565b505050600190565b9190820180921161048757565b6004356001600160a01b03811681036101a05790565b6044356001600160a01b03811681036101a05790565b356001600160a01b03811681036101a05790565b989796959493929190604051997fd5bba88286cccde9162e20a797ff293aac0b11190037e71286b8a5271985e4cb60208c015260408b015260608a0152608089015260a088015260c087015260e08601526101008501526101208401526101408301526101408252611ad26101608361191a565b565b6001600160401b0381116104735760051b60200190565b903590601e19813603018212156101a057018035906001600160401b0382116101a0576020019181360383136101a057565b80518210156118d05760209160051b010190565b91908110156118d05760051b8101359060be19813603018212156101a0570190565b916040519360605260405260601b602c526323b872dd60601b600c5260205f6064601c82855af1908160015f51141615611b93575b50505f606052604052565b3b153d171015611ba4575f80611b88565b637939f4245f526004601cfd5b916117f591611bbf93611c17565b15610c9b57565b919060145260345263a9059cbb60601b5f5260205f6044601082855af1908160015f51141615611bf9575b50505f603452565b3b153d171015611c0a575f80611bf1565b6390b8ec185f526004601cfd5b604080515f95949093918114611c6257604114611c3357505050565b604080929395508101355f1a60205281375b5f526020604060805f60015afa505f6060523d6060185191604052565b5060208082013560ff81901c601b0190915290356040526001600160ff1b0316606052909250611c4556fea2646970667358221220759248af50aaddb85c7923e0a741f511253ffd21881e408db3f18ad98ccafffb64736f6c634300081e0033"},"sourceId":"src/DepositVault.sol","sourcemap":"325:24671:15:-:0;;;;;;;;;;;;;-1:-1:-1;;325:24671:15;;;;-1:-1:-1;;;;;325:24671:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;1329:5;;325:24671;-1:-1:-1;;;;;325:24671:15;;;;7267:20;;7263:46;;-1:-1:-1;;;;;325:24671:15;;7323:32;;7319:58;;325:24671;;;;;;-1:-1:-1;325:24671:15;;;-1:-1:-1;325:24671:15;;;;;;;7411:38;325:24671;;;7411:38;325:24671;;;;;;;;;;7319:58;7296:13;;;-1:-1:-1;7364:13:15;;-1:-1:-1;7364:13:15;325:24671;-1:-1:-1;325:24671:15;;;;;;-1:-1:-1;325:24671:15;;;;;-1:-1:-1;325:24671:15;;;;-1:-1:-1;;;;;325:24671:15;;;;;;:::o","userdoc":{"errors":{"EmptyOrders()":[{"notice":"Reverts if an order array is empty."}],"Expired()":[{"notice":"Reverts if a signed operation is past its deadline."}],"InsufficientAdministrators(uint256,uint256)":[{"notice":"Reverts if insufficient administrators are provided when setting the administrators"}],"InsufficientAmountFromExecutor(uint256,uint256)":[{"notice":"Reverts if a settlement callback returns an insufficient input token amount"}],"InvalidNonce(uint256,uint256)":[{"notice":"Reverts if the nonce used in a transaction is incorrect."}],"InvalidSignature()":[{"notice":"Reverts if the signature provided is invalid."}],"MissedQuorum(uint256,uint256)":[{"notice":"Reverts when an insufficient number of signatures are provided for a withdrawal request"}],"NotAdmin()":[{"notice":"Reverts if the caller is not an admin."}],"NotCredentialManager()":[{"notice":"Reverts if the caller is not the credential manager"}],"NotExecutor()":[{"notice":"Reverts if the caller is not the authorized executor."}],"NotOwner()":[{"notice":"Reverts if the caller is not the owner."}],"TooSoon()":[{"notice":"Reverts if an insufficient number of blocks have elapsed since the last signature use"}],"ZeroAddress()":[{"notice":"Reverts when given the zero address."}],"ZeroWithdrawalQuorum()":[{"notice":"Reverts if a new withdrawal quorum value is equal to zero"}]},"events":{"AdminAdded(address,uint256)":{"notice":"Signals that a new administrator has been added to the vault"},"AdministratorSetReset()":{"notice":"Indicates that the set of administrators has been cleared and is now empty"},"CredentialManagerChanged(address,address)":{"notice":"Signals that the credential manager address has changed"},"Deposited(bytes32,uint64,uint256,address,uint256)":{"notice":"Signals a deposit."},"Settled(bytes32,uint64,uint256,address,uint256,address,uint256)":{"notice":"Signals a settlement."},"WithdrawalQuorumChanged(uint256,uint256)":{"notice":"Signals that the withdrawal quorum has changed"},"Withdrew(bytes32,uint64,uint256,address,uint256)":{"notice":"Signals a withdrawal."}},"kind":"user","methods":{"addSettlerExecutor(bytes32,address)":{"notice":"Sets the settle executor."},"administrators(uint256)":{"notice":"Set of administrators"},"approvedSettlers(uint256)":{"notice":"List of all approved settler IDs."},"constructor":{"notice":"Initializes the contract and sets the owner."},"credentialManager()":{"notice":"The address responsible for adding or removing administrators"},"deposit(bytes32,uint64,address,uint256)":{"notice":"Deposits a token into the vault."},"depositCounts(bytes32,uint64)":{"notice":"Maps (settler ID, account_index) pairs to their deposit count (nonce)."},"executeAtomicSettlement((address,uint256,address,uint256,uint256),bytes32,uint64,uint256,bytes,bytes)":{"notice":"Executes an atomic settlement."},"getApprovedSettlers()":{"notice":"Get the array of approved settlers."},"lastSignatureUse()":{"notice":"Block number of latest signature use"},"owner()":{"notice":"The admin approves settlements and withdrawals."},"pendingSettlements(bytes32,uint64,uint256)":{"notice":"Maps (settler ID, account_index) pairs to their queue of pending batch settlements."},"pullBatchSettlement(((address,uint256,address,uint256,uint256),bytes)[],bytes32,uint64,address,uint256)":{"notice":"Pulls funds for execution during a settlement batch."},"pushBatchSettlements(bytes32,uint64)":{"notice":"Pushes expected funds from a batch settlement to the deposit vault."},"removeSettler(bytes32)":{"notice":"Removes a settler."},"setDomainSeparator(bytes32)":{"notice":"Sets the domain separators for EIP-712 signatures."},"setOwner(address)":{"notice":"Sets the owner of the vault."},"settlementCaps(address)":{"notice":"Maximum total tokens that can be settled in a single block for each token."},"settlementCounts(bytes32,uint64)":{"notice":"Maps (settler ID, account_index) pairs to their settlement count (nonce)."},"withdraw((address,uint256,uint256),bytes32,uint64,address,uint256,bytes32,bytes[])":{"notice":"Withdraws a token from the vault."},"withdrawalCounts(bytes32,uint64)":{"notice":"Maps (settler ID, account_index) pairs to their withdrawal count (nonce)."},"withdrawalQuorum()":{"notice":"Minimum number of administrator signatures to approve a withdrawal request"}},"version":1}},"IAdminUpdateStrategy":{"abi":[{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address[]","name":"newAdministrators","type":"address[]"},{"internalType":"uint256","name":"newWithdrawalQuorum","type":"uint256"}],"name":"setAdministrators","outputs":[],"stateMutability":"payable","type":"function"}],"contractName":"IAdminUpdateStrategy","deploymentBytecode":{"bytecode":"0x"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"setAdministrators(address,address[],uint256)":"0x075034ae"},"runtimeBytecode":{"bytecode":"0x"},"sourceId":"src/interfaces/IAdminUpdateStrategy.sol","sourcemap":"","userdoc":{"kind":"user","methods":{},"version":1}},"IAtomicSettlementCallback":{"abi":[{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onAtomicSettlement","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}],"contractName":"IAtomicSettlementCallback","deploymentBytecode":{"bytecode":"0x"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"onAtomicSettlement(address,uint256,bytes)":"0x3f1d584e"},"runtimeBytecode":{"bytecode":"0x"},"sourceId":"src/interfaces/IAtomicSettlementCallback.sol","sourcemap":"","userdoc":{"kind":"user","methods":{"onAtomicSettlement(address,uint256,bytes)":{"notice":"Computes the minimum expected quantity of `token` that will be received by the deposit vault upon execution of an atomic settlement request"}},"version":1}},"IAutomataDcapAttestation":{"abi":[{"inputs":[{"internalType":"bytes","name":"output","type":"bytes"},{"internalType":"enum IAutomataDcapAttestation.ZkCoProcessorType","name":"zkvm","type":"uint8"},{"internalType":"bytes","name":"proofBytes","type":"bytes"}],"name":"verifyAndAttestWithZKProof","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"errorData","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}],"contractName":"IAutomataDcapAttestation","deploymentBytecode":{"bytecode":"0x"},"devdoc":{"details":"Bindings for the 'AutomataDcapAttestation' contract. Compatible with Automata V3 ZK Coprocessor logic.","kind":"dev","methods":{"verifyAndAttestWithZKProof(bytes,uint8,bytes)":{"params":{"output":"The Public Values (Journal) - effectively the Quote Body.","proofBytes":"The actual (Groth16) proof.","zkvm":"The type of ZKVM used."},"returns":{"errorData":"Error message if failed, or empty if success.","success":"True if valid."}}},"version":1},"methodIdentifiers":{"verifyAndAttestWithZKProof(bytes,uint8,bytes)":"0x57859ce0"},"runtimeBytecode":{"bytecode":"0x"},"sourceId":"src/interfaces/IAutomataDcapAttestation.sol","sourcemap":"","userdoc":{"kind":"user","methods":{"verifyAndAttestWithZKProof(bytes,uint8,bytes)":{"notice":"Verifies a SNARK proof (Groth16) for a TEE Quote."}},"notice":"Interface for Automata's DCAP Attestation Verifier (V3)","version":1}},"ICheckpointer":{"abi":[{"inputs":[],"name":"AlreadySet","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotCouncilMultisig","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string[]","name":"approvedWithdrawals","type":"string[]"}],"name":"Withdrawals","type":"event"},{"inputs":[],"name":"CHECKPOINT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"sharedSignature","type":"bytes"},{"internalType":"bytes","name":"leaderSignature","type":"bytes"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint8[]","name":"stateRoot","type":"uint8[]"},{"internalType":"string[]","name":"approvedWithdrawals","type":"string[]"}],"internalType":"struct ICheckpointer.Checkpoint","name":"_checkpoint","type":"tuple"}],"name":"checkpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"councilMultisig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"leader","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"}],"name":"setDomainSeparator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCouncilMultisig","type":"address"}],"name":"setInitialCouncilMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newLeader","type":"address"}],"name":"setLeader","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCouncilMultisig","type":"address"}],"name":"setNewCouncilMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stateRoot","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stateRootNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"contractName":"ICheckpointer","deploymentBytecode":{"bytecode":"0x"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"CHECKPOINT_TYPEHASH()":"0xe1193e4c","admin()":"0xf851a440","checkpoint(bytes,bytes,(uint256,uint8[],string[]))":"0x8bbb26a3","councilMultisig()":"0x07ddaf53","leader()":"0x40eedabb","setAdmin(address)":"0x704b6c02","setDomainSeparator(bytes32)":"0x7438b937","setInitialCouncilMultisig(address)":"0x3ea987d3","setLeader(address)":"0x4331e8dd","setNewCouncilMultisig(address)":"0x5fa993b2","stateRoot(uint256)":"0xcc2fc845","stateRootNonce()":"0x74ebc7a0"},"runtimeBytecode":{"bytecode":"0x"},"sourceId":"src/interfaces/ICheckpointer.sol","sourcemap":"","userdoc":{"kind":"user","methods":{},"version":1}},"ICredentialManager":{"abi":[{"inputs":[],"name":"NoStrategy","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"StrategyAlreadyExists","type":"error"},{"inputs":[{"internalType":"uint256","name":"routingId","type":"uint256"},{"internalType":"uint256","name":"vmId","type":"uint256"}],"name":"VaultNotFound","type":"error"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"uint8","name":"routingId","type":"uint8"},{"internalType":"uint256","name":"vmId","type":"uint256"},{"internalType":"bytes32","name":"addr","type":"bytes32"},{"components":[{"internalType":"uint64","name":"blockTimeMs","type":"uint64"},{"internalType":"uint8","name":"defaultConfirmations","type":"uint8"},{"internalType":"uint8","name":"depositIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"withdrawalIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"settlementIngestConfirmations","type":"uint8"}],"internalType":"struct ICredentialManager.ChainConfig","name":"config","type":"tuple"}],"name":"addVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"adminUpdateStrategies","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"start","type":"uint16"},{"internalType":"uint16","name":"end","type":"uint16"}],"name":"getVaults","outputs":[{"components":[{"internalType":"uint8","name":"routingId","type":"uint8"},{"internalType":"uint64","name":"vmId","type":"uint64"},{"internalType":"bytes32","name":"vaultAddress","type":"bytes32"},{"components":[{"internalType":"uint64","name":"blockTimeMs","type":"uint64"},{"internalType":"uint8","name":"defaultConfirmations","type":"uint8"},{"internalType":"uint8","name":"depositIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"withdrawalIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"settlementIngestConfirmations","type":"uint8"}],"internalType":"struct ICredentialManager.ChainConfig","name":"config","type":"tuple"}],"internalType":"struct ICredentialManager.Vault[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"routingId","type":"uint256"},{"internalType":"uint256","name":"vmId","type":"uint256"},{"internalType":"address","name":"strategy","type":"address"}],"name":"registerAdminUpdateStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"idx","type":"uint256"}],"name":"removeVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"routingId","type":"uint256"},{"internalType":"uint256","name":"vmId","type":"uint256"},{"internalType":"address[]","name":"newAdministrators","type":"address[]"},{"internalType":"uint256","name":"newWithdrawalQuorum","type":"uint256"}],"name":"setDepositVaultAdministrators","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vaults","outputs":[{"internalType":"uint8","name":"routingId","type":"uint8"},{"internalType":"uint256","name":"vmId","type":"uint256"},{"internalType":"bytes32","name":"vaultAddress","type":"bytes32"},{"components":[{"internalType":"uint64","name":"blockTimeMs","type":"uint64"},{"internalType":"uint8","name":"defaultConfirmations","type":"uint8"},{"internalType":"uint8","name":"depositIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"withdrawalIngestConfirmations","type":"uint8"},{"internalType":"uint8","name":"settlementIngestConfirmations","type":"uint8"}],"internalType":"struct ICredentialManager.ChainConfig","name":"config","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}],"contractName":"ICredentialManager","deploymentBytecode":{"bytecode":"0x"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"addVault(uint8,uint256,bytes32,(uint64,uint8,uint8,uint8,uint8))":"0x8e723ccc","admin()":"0xf851a440","adminUpdateStrategies(uint256,uint256)":"0x3174b727","getVaults(uint16,uint16)":"0x9fd7285c","registerAdminUpdateStrategy(uint256,uint256,address)":"0x54491683","removeVault(uint256)":"0xeaadd976","setDepositVaultAdministrators(uint256,uint256,address[],uint256)":"0x9ebc068e","vaults(uint256)":"0x8c64ea4a","withdraw(address)":"0x51cff8d9"},"runtimeBytecode":{"bytecode":"0x"},"sourceId":"src/interfaces/ICredentialManager.sol","sourcemap":"","userdoc":{"kind":"user","methods":{},"version":1}},"IDepositVault":{"abi":[{"inputs":[],"name":"EmptyOrders","type":"error"},{"inputs":[],"name":"Expired","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"InsufficientAdministrators","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"given","type":"uint256"}],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"provided","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"MissedQuorum","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotCredentialManager","type":"error"},{"inputs":[],"name":"NotExecutor","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"TooSoon","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroWithdrawalQuorum","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"},{"indexed":false,"internalType":"uint256","name":"numAdminsAfter","type":"uint256"}],"name":"AdminAdded","type":"event"},{"anonymous":false,"inputs":[],"name":"AdministratorSetReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldCredentialManager","type":"address"},{"indexed":false,"internalType":"address","name":"newCredentialManager","type":"address"}],"name":"CredentialManagerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"Settled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"current","type":"uint256"}],"name":"WithdrawalQuorumChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"user","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrew","type":"event"},{"inputs":[],"name":"ORDER_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"settler","type":"bytes32"},{"internalType":"address","name":"executor","type":"address"}],"name":"addSettlerExecutor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"administrators","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"approvedSettlers","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"canDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"credentialManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"credentialManagerChangeDelayBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"depositCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IDepositVault.Settlement","name":"order","type":"tuple"},{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"executeAtomicSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getApprovedSettlers","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAdministrator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastSignatureUse","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ownerWithdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pendingSettlements","outputs":[{"components":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IDepositVault.Settlement","name":"settlement","type":"tuple"},{"internalType":"address","name":"target","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IDepositVault.Settlement","name":"settlement","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct IDepositVault.SignedSettlement[]","name":"orders","type":"tuple[]"},{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"validUntil","type":"uint256"}],"name":"pullBatchSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"user","type":"bytes32"}],"name":"pushBatchSettlements","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"settler","type":"bytes32"}],"name":"removeSettler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"newAdministrators","type":"address[]"},{"internalType":"uint256","name":"newWithdrawalQuorum","type":"uint256"}],"name":"setAdministrators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCredentialManager","type":"address"}],"name":"setCredentialManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setDepositorStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"}],"name":"setDomainSeparator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"settlementCaps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"settlementCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct IDepositVault.Withdrawal","name":"withdrawal","type":"tuple"},{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"bytes32","name":"epochHash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"withdrawalCounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalQuorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"contractName":"IDepositVault","deploymentBytecode":{"bytecode":"0x"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"ORDER_TYPEHASH()":"0xf973a209","addSettlerExecutor(bytes32,address)":"0xad9fa8bc","administrators(uint256)":"0xd89d1510","approvedSettlers(uint256)":"0x3a87fe4d","canDeposit(address)":"0x4bf0d331","credentialManager()":"0x2b0c1a1e","credentialManagerChangeDelayBlocks()":"0xa33c9d00","deposit(bytes32,address,uint256)":"0xd954863c","depositCounts(bytes32)":"0x3d63ea93","executeAtomicSettlement((address,uint256,address,uint256,uint256),bytes32,uint256,bytes,bytes)":"0xbf5b0e6f","getApprovedSettlers()":"0x92698ac6","isAdministrator(address)":"0x0a2eb301","lastSignatureUse()":"0xd8c8785d","owner()":"0x8da5cb5b","ownerWithdrawToken(address,address,uint256)":"0xf585b64f","pendingSettlements(bytes32,uint256)":"0x2fe7a797","pullBatchSettlement(((address,uint256,address,uint256,uint256),bytes)[],bytes32,address,uint256)":"0x9a39f344","pushBatchSettlements(bytes32)":"0xc8c57ba6","removeSettler(bytes32)":"0x41774bfe","setAdministrators(address[],uint256)":"0x23c56731","setCredentialManager(address)":"0x21e6652c","setDepositorStatus(address,bool)":"0x224b93e1","setDomainSeparator(bytes32)":"0x7438b937","setOwner(address)":"0x13af4035","settlementCaps(address)":"0x98af9772","settlementCounts(bytes32)":"0xa815476f","withdraw((address,uint256,uint256),bytes32,address,uint256,bytes32,bytes)":"0x3b3c2a03","withdrawalCounts(bytes32)":"0x82ff8b1e","withdrawalQuorum()":"0x93ea8a7d"},"runtimeBytecode":{"bytecode":"0x"},"sourceId":"src/interfaces/IDepositVault.sol","sourcemap":"","userdoc":{"kind":"user","methods":{},"version":1}},"IL1CrossDomainMessenger":{"abi":[{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"}],"contractName":"IL1CrossDomainMessenger","deploymentBytecode":{"bytecode":"0x"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"sendMessage(address,bytes,uint32)":"0x3dbb202b"},"runtimeBytecode":{"bytecode":"0x"},"sourceId":"src/strategies/OPStackAdminUpdateStrategy.sol","sourcemap":"","userdoc":{"kind":"user","methods":{},"version":1}},"IRegistry":{"abi":[{"inputs":[],"name":"ChainAlreadyExists","type":"error"},{"inputs":[],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidBufferMultiple","type":"error"},{"inputs":[],"name":"InvalidCollateralFactor","type":"error"},{"inputs":[],"name":"InvalidInitialMarginsClamps","type":"error"},{"inputs":[],"name":"InvalidInitialMarginsConfiguration","type":"error"},{"inputs":[],"name":"InvalidInitialMarginsFactors","type":"error"},{"inputs":[],"name":"InvalidInterestKinks","type":"error"},{"inputs":[],"name":"InvalidLiabilityFactor","type":"error"},{"inputs":[],"name":"InvalidMaxFundingRate","type":"error"},{"inputs":[],"name":"InvalidMaxUtilizationRate","type":"error"},{"inputs":[],"name":"InvalidRateInterestKinks","type":"error"},{"inputs":[],"name":"InvalidUSDInterestKinks","type":"error"},{"inputs":[],"name":"InvalidUSDRateInterestKinks","type":"error"},{"inputs":[],"name":"InvalidUtilizationCap","type":"error"},{"inputs":[{"internalType":"uint16","name":"asset","type":"uint16"}],"name":"NoPendingRiskParameters","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotRiskManager","type":"error"},{"inputs":[],"name":"RiskManagerNotSet","type":"error"},{"inputs":[{"internalType":"uint16","name":"asset","type":"uint16"},{"internalType":"uint256","name":"eligibleAt","type":"uint256"}],"name":"TooSoon","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"chain","type":"uint64"},{"indexed":false,"internalType":"uint16","name":"index","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"current","type":"uint256"}],"name":"Max1HrDepositChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"chain","type":"uint64"},{"indexed":false,"internalType":"uint16","name":"index","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"current","type":"uint256"}],"name":"MaxDepositChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"chain","type":"uint64"},{"indexed":false,"internalType":"uint16","name":"index","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"current","type":"uint256"}],"name":"MinWeightChanged","type":"event"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"index","type":"uint16"}],"name":"applyPendingRiskParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeAccount","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint16","name":"index","type":"uint16"}],"name":"getAssetData","outputs":[{"components":[{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"bytes32","name":"assetAddress","type":"bytes32"},{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint256","name":"maxDeposits","type":"uint256"},{"internalType":"uint256","name":"max1hrDeposits","type":"uint256"},{"internalType":"uint256","name":"minWeight","type":"uint256"}],"internalType":"struct IRegistry.AssetData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"bytes32","name":"assetAddress","type":"bytes32"}],"name":"getAssetIndex","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"start","type":"uint16"},{"internalType":"uint16","name":"end","type":"uint16"}],"name":"getAssets","outputs":[{"components":[{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"bytes32","name":"assetAddress","type":"bytes32"},{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint256","name":"maxDeposits","type":"uint256"},{"internalType":"uint256","name":"max1hrDeposits","type":"uint256"},{"internalType":"uint256","name":"minWeight","type":"uint256"}],"internalType":"struct IRegistry.AssetData[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"start","type":"uint16"},{"internalType":"uint16","name":"end","type":"uint16"}],"name":"getRiskParameters","outputs":[{"components":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxSpotOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxUtilization","type":"uint256"},{"internalType":"bool","name":"isolatedOnly","type":"bool"},{"internalType":"uint256[]","name":"interestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"kinkInterestRates","type":"uint256[]"},{"internalType":"uint256[]","name":"usdInterestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"usdKinkInterestRates","type":"uint256[]"},{"internalType":"uint256","name":"skewModifier","type":"uint256"},{"internalType":"uint256","name":"skewCliff","type":"uint256"},{"internalType":"int256","name":"baseFundingRate","type":"int256"},{"internalType":"uint256","name":"premiumClamp","type":"uint256"},{"internalType":"uint256[]","name":"initialMarginClamps","type":"uint256[]"},{"internalType":"uint256[]","name":"initialMarginFactors","type":"uint256[]"},{"internalType":"uint256","name":"maxFundingRate","type":"uint256"},{"internalType":"uint256","name":"maxUtilizationRate","type":"uint256"},{"internalType":"uint256","name":"bufferMultiple","type":"uint256"}],"internalType":"struct IRegistry.RiskParameters[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"pendingRiskParameters","outputs":[{"components":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxSpotOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxUtilization","type":"uint256"},{"internalType":"bool","name":"isolatedOnly","type":"bool"},{"internalType":"uint256[]","name":"interestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"kinkInterestRates","type":"uint256[]"},{"internalType":"uint256[]","name":"usdInterestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"usdKinkInterestRates","type":"uint256[]"},{"internalType":"uint256","name":"skewModifier","type":"uint256"},{"internalType":"uint256","name":"skewCliff","type":"uint256"},{"internalType":"int256","name":"baseFundingRate","type":"int256"},{"internalType":"uint256","name":"premiumClamp","type":"uint256"},{"internalType":"uint256[]","name":"initialMarginClamps","type":"uint256[]"},{"internalType":"uint256[]","name":"initialMarginFactors","type":"uint256[]"},{"internalType":"uint256","name":"maxFundingRate","type":"uint256"},{"internalType":"uint256","name":"maxUtilizationRate","type":"uint256"},{"internalType":"uint256","name":"bufferMultiple","type":"uint256"}],"internalType":"struct IRegistry.RiskParameters","name":"parameters","type":"tuple"},{"internalType":"uint256","name":"validAfter","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"riskManagerMultisig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"riskParameterChangeDelaySeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"riskParameters","outputs":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxSpotOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxUtilization","type":"uint256"},{"internalType":"bool","name":"isolatedOnly","type":"bool"},{"internalType":"uint256","name":"skewModifier","type":"uint256"},{"internalType":"uint256","name":"skewCliff","type":"uint256"},{"internalType":"int256","name":"baseFundingRate","type":"int256"},{"internalType":"uint256","name":"premiumClamp","type":"uint256"},{"internalType":"uint256","name":"maxFundingRate","type":"uint256"},{"internalType":"uint256","name":"maxUtilizationRate","type":"uint256"},{"internalType":"uint256","name":"bufferMultiple","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"bytes32","name":"assetAddress","type":"bytes32"},{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint256","name":"maxDeposits","type":"uint256"},{"internalType":"uint256","name":"max1hrDeposits","type":"uint256"},{"internalType":"uint256","name":"minWeight","type":"uint256"}],"internalType":"struct IRegistry.AssetData","name":"data","type":"tuple"}],"name":"setAssetData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"account","type":"bytes32"}],"name":"setFeeAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chain","type":"uint16"},{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"uint256","name":"newMaxDeposit","type":"uint256"}],"name":"setMax1HrDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chain","type":"uint16"},{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"uint256","name":"newMaxDeposit","type":"uint256"}],"name":"setMaxDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chain","type":"uint16"},{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"uint256","name":"newMinWeight","type":"uint256"}],"name":"setMinWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"index","type":"uint16"},{"components":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxSpotOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxUtilization","type":"uint256"},{"internalType":"bool","name":"isolatedOnly","type":"bool"},{"internalType":"uint256[]","name":"interestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"kinkInterestRates","type":"uint256[]"},{"internalType":"uint256[]","name":"usdInterestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"usdKinkInterestRates","type":"uint256[]"},{"internalType":"uint256","name":"skewModifier","type":"uint256"},{"internalType":"uint256","name":"skewCliff","type":"uint256"},{"internalType":"int256","name":"baseFundingRate","type":"int256"},{"internalType":"uint256","name":"premiumClamp","type":"uint256"},{"internalType":"uint256[]","name":"initialMarginClamps","type":"uint256[]"},{"internalType":"uint256[]","name":"initialMarginFactors","type":"uint256[]"},{"internalType":"uint256","name":"maxFundingRate","type":"uint256"},{"internalType":"uint256","name":"maxUtilizationRate","type":"uint256"},{"internalType":"uint256","name":"bufferMultiple","type":"uint256"}],"internalType":"struct IRegistry.RiskParameters","name":"parameters","type":"tuple"}],"name":"setPendingRiskParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"multisig","type":"address"}],"name":"setRiskManagerMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxSpotOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxUtilization","type":"uint256"},{"internalType":"bool","name":"isolatedOnly","type":"bool"},{"internalType":"uint256[]","name":"interestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"kinkInterestRates","type":"uint256[]"},{"internalType":"uint256[]","name":"usdInterestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"usdKinkInterestRates","type":"uint256[]"},{"internalType":"uint256","name":"skewModifier","type":"uint256"},{"internalType":"uint256","name":"skewCliff","type":"uint256"},{"internalType":"int256","name":"baseFundingRate","type":"int256"},{"internalType":"uint256","name":"premiumClamp","type":"uint256"},{"internalType":"uint256[]","name":"initialMarginClamps","type":"uint256[]"},{"internalType":"uint256[]","name":"initialMarginFactors","type":"uint256[]"},{"internalType":"uint256","name":"maxFundingRate","type":"uint256"},{"internalType":"uint256","name":"maxUtilizationRate","type":"uint256"},{"internalType":"uint256","name":"bufferMultiple","type":"uint256"}],"internalType":"struct IRegistry.RiskParameters","name":"params","type":"tuple"}],"name":"validateRiskParameters","outputs":[],"stateMutability":"pure","type":"function"}],"contractName":"IRegistry","deploymentBytecode":{"bytecode":"0x"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"admin()":"0xf851a440","applyPendingRiskParameters(uint16)":"0x6cbb0b54","feeAccount()":"0x65e17c9d","getAssetData(uint64,uint16)":"0xf247ceb9","getAssetIndex(uint64,bytes32)":"0x39006126","getAssets(uint16,uint16)":"0x0cb661c7","getRiskParameters(uint16,uint16)":"0xf0fef575","pendingRiskParameters(uint16)":"0xa812e224","riskManagerMultisig()":"0x525ea8b7","riskParameterChangeDelaySeconds()":"0x04cd46f9","riskParameters(uint16)":"0x114bb9c5","setAdmin(address)":"0x704b6c02","setAssetData((uint16,bytes32,uint64,uint256,uint256,uint256))":"0xe4380c93","setFeeAccount(bytes32)":"0xe2a0a600","setMax1HrDeposits(uint16,uint16,uint256)":"0x3c0f2a2f","setMaxDeposits(uint16,uint16,uint256)":"0xe492729d","setMinWeight(uint16,uint16,uint256)":"0xc515c8c6","setPendingRiskParameters(uint16,(uint8,uint8,uint256,uint256,uint256,uint256,bool,uint256[],uint256[],uint256[],uint256[],uint256,uint256,int256,uint256,uint256[],uint256[],uint256,uint256,uint256))":"0xb4bb0646","setRiskManagerMultisig(address)":"0x4ffcbdfb","validateRiskParameters((uint8,uint8,uint256,uint256,uint256,uint256,bool,uint256[],uint256[],uint256[],uint256[],uint256,uint256,int256,uint256,uint256[],uint256[],uint256,uint256,uint256))":"0x57990261"},"runtimeBytecode":{"bytecode":"0x"},"sourceId":"src/interfaces/IRegistry.sol","sourcemap":"","userdoc":{"kind":"user","methods":{},"version":1}},"IntraChainAdminUpdateStrategy":{"abi":[{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address[]","name":"newAdministrators","type":"address[]"},{"internalType":"uint256","name":"newWithdrawalQuorum","type":"uint256"}],"name":"setAdministrators","outputs":[],"stateMutability":"payable","type":"function"}],"contractName":"IntraChainAdminUpdateStrategy","deploymentBytecode":{"bytecode":"0x6080806040523460155761017e908161001a8239f35b5f80fdfe6080806040526004361015610012575f80fd5b5f905f3560e01c63075034ae14610027575f80fd5b6060366003190112610144576004356001600160a01b038116908190036101445760243567ffffffffffffffff8111610144573660238201121561014457806004013567ffffffffffffffff8111610144573660248260051b8401011161014457823b15610144579083916323c5673160e01b8352806044840160406004860152526024606484019201905f905b8082106101145750505091815f818195604435602483015203925af18015610109576100df575080f35b905067ffffffffffffffff81116100f557604052005b634e487b7160e01b5f52604160045260245ffd5b6040513d5f823e3d90fd5b9193509183356001600160a01b0381169190829003610144576020816001938293520194019201859392916100b5565b5f80fdfea26469706673582212202e107e1054c7643167531235c2ca21a0a676fb179958378fd086626f108417fa64736f6c634300081e0033"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"setAdministrators(address,address[],uint256)":"0x075034ae"},"runtimeBytecode":{"bytecode":"0x6080806040526004361015610012575f80fd5b5f905f3560e01c63075034ae14610027575f80fd5b6060366003190112610144576004356001600160a01b038116908190036101445760243567ffffffffffffffff8111610144573660238201121561014457806004013567ffffffffffffffff8111610144573660248260051b8401011161014457823b15610144579083916323c5673160e01b8352806044840160406004860152526024606484019201905f905b8082106101145750505091815f818195604435602483015203925af18015610109576100df575080f35b905067ffffffffffffffff81116100f557604052005b634e487b7160e01b5f52604160045260245ffd5b6040513d5f823e3d90fd5b9193509183356001600160a01b0381169190829003610144576020816001938293520194019201859392916100b5565b5f80fdfea26469706673582212202e107e1054c7643167531235c2ca21a0a676fb179958378fd086626f108417fa64736f6c634300081e0033"},"sourceId":"src/strategies/IntraChainAdminUpdateStrategy.sol","sourcemap":"290:322:25:-:0;;;;;;;;;;;;;;;;;","userdoc":{"kind":"user","methods":{},"notice":"Use this strategy when updating the vault on the same chain as the credential manager.","version":1}},"MockTarget":{"abi":[{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onAtomicSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"}],"contractName":"MockTarget","deploymentBytecode":{"bytecode":"0x6080806040523460135760b1908160188239f35b5f80fdfe6004361015600b575f80fd5b5f3560e01c633f1d584e14601d575f80fd5b3460775760603660031901126077576004356001600160a01b0381160360775760443567ffffffffffffffff811160775736602382011215607757806004013567ffffffffffffffff811160775736910160240111607757005b5f80fdfea26469706673582212206cf91bafe3a0f54d58f9735d82a4757234fa3d217135826792ecef05e5d5837c64736f6c634300081c0033"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"onAtomicSettlement(address,uint256,bytes)":"0x3f1d584e"},"runtimeBytecode":{"bytecode":"0x6004361015600b575f80fd5b5f3560e01c633f1d584e14601d575f80fd5b3460775760603660031901126077576004356001600160a01b0381160360775760443567ffffffffffffffff811160775736602382011215607757806004013567ffffffffffffffff811160775736910160240111607757005b5f80fdfea26469706673582212206cf91bafe3a0f54d58f9735d82a4757234fa3d217135826792ecef05e5d5837c64736f6c634300081c0033"},"sourceId":"src/MockTarget.sol","sourcemap":"149:148:4:-:0;;;;;;;;;;;;;;;;;","userdoc":{"kind":"user","methods":{},"version":1}},"OPStackAdminUpdateStrategy":{"abi":[{"inputs":[{"internalType":"address","name":"l1CrossDomainMessenger","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ZeroMessengerAddress","type":"error"},{"inputs":[],"name":"L1_CROSS_DOMAIN_MESSENGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L2_GAS_LIMIT","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address[]","name":"newAdministrators","type":"address[]"},{"internalType":"uint256","name":"newWithdrawalQuorum","type":"uint256"}],"name":"setAdministrators","outputs":[],"stateMutability":"payable","type":"function"}],"contractName":"OPStackAdminUpdateStrategy","deploymentBytecode":{"bytecode":"0x60a034608057601f61033938819003918201601f19168301916001600160401b03831184841017608457808492602094604052833981010312608057516001600160a01b038116808203608057156071576080526040516102a090816100998239608051818181605401526101590152f35b637dc8404d60e01b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f905f3560e01c908163075034ae146100a4575080635e743ef7146100865763f904facb1461003f575f80fd5b346100835780600319360112610083576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b80fd5b50346100835780600319360112610083576020604051622dc6c08152f35b90506060366003190112610200576004356001600160a01b03811690819003610200576024359167ffffffffffffffff831161020057366023840112156102005782600401359267ffffffffffffffff8411610200573660248560051b8301011161020057928160208101946323c5673160e01b8652826064830160406024850152526024608483019101925f905b8082106102045750506101579250604435604483015203601f198101835282610234565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b15610200575f926084604051809681958294633dbb202b60e01b84526004840152606060248401525180918160648501528484015e8181018301879052622dc6c06044830152601f01601f1916810103019134905af180156101f5576101e7575080f35b6101f391505f90610234565b005b6040513d5f823e3d90fd5b5f80fd5b9092509083356001600160a01b038116919082900361020057602081600193829352019401920184929391610133565b90601f8019910116810190811067ffffffffffffffff82111761025657604052565b634e487b7160e01b5f52604160045260245ffdfea264697066735822122004f87248a949ed7aa2c0a05b9a4143d56eee5dc0be463317275b1915e6f76ba564736f6c634300081e0033"},"devdoc":{"kind":"dev","methods":{"setAdministrators(address,address[],uint256)":{"details":"Sends a cross-domain message from L1 \u2192 L2 using the OP Stack messengerForwards msg.value directly to the L1 messenger","params":{"newAdministrators":"The full administrator set","newWithdrawalQuorum":"The withdrawal quorum","vault":"The L2 vault address"}}},"version":1},"methodIdentifiers":{"L1_CROSS_DOMAIN_MESSENGER()":"0xf904facb","L2_GAS_LIMIT()":"0x5e743ef7","setAdministrators(address,address[],uint256)":"0x075034ae"},"runtimeBytecode":{"bytecode":"0x6080806040526004361015610012575f80fd5b5f905f3560e01c908163075034ae146100a4575080635e743ef7146100865763f904facb1461003f575f80fd5b346100835780600319360112610083576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b80fd5b50346100835780600319360112610083576020604051622dc6c08152f35b90506060366003190112610200576004356001600160a01b03811690819003610200576024359167ffffffffffffffff831161020057366023840112156102005782600401359267ffffffffffffffff8411610200573660248560051b8301011161020057928160208101946323c5673160e01b8652826064830160406024850152526024608483019101925f905b8082106102045750506101579250604435604483015203601f198101835282610234565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b15610200575f926084604051809681958294633dbb202b60e01b84526004840152606060248401525180918160648501528484015e8181018301879052622dc6c06044830152601f01601f1916810103019134905af180156101f5576101e7575080f35b6101f391505f90610234565b005b6040513d5f823e3d90fd5b5f80fd5b9092509083356001600160a01b038116919082900361020057602081600193829352019401920184929391610133565b90601f8019910116810190811067ffffffffffffffff82111761025657604052565b634e487b7160e01b5f52604160045260245ffdfea264697066735822122004f87248a949ed7aa2c0a05b9a4143d56eee5dc0be463317275b1915e6f76ba564736f6c634300081e0033"},"sourceId":"src/strategies/OPStackAdminUpdateStrategy.sol","sourcemap":"446:1455:26:-:0;;;;;;;;;;;;;-1:-1:-1;;446:1455:26;;;;-1:-1:-1;;;;;446:1455:26;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;446:1455:26;;;;;;;868:36;864:71;;945:50;;446:1455;;;;;;;;945:50;446:1455;;;;;;;;;;;864:71;913:22;;;-1:-1:-1;913:22:26;;-1:-1:-1;913:22:26;446:1455;-1:-1:-1;446:1455:26;;;;;;-1:-1:-1;446:1455:26;;;;;-1:-1:-1;446:1455:26","userdoc":{"errors":{"ZeroMessengerAddress()":[{"notice":"Reverts if messenger address is zero."}]},"kind":"user","methods":{"L1_CROSS_DOMAIN_MESSENGER()":{"notice":"L1 CrossDomainMessenger."},"L2_GAS_LIMIT()":{"notice":"Conservative gas limit for L2 execution."},"setAdministrators(address,address[],uint256)":{"notice":"Updates the administrator set and withdrawal quorum on an OP Stack L2 vault"}},"notice":"Admin update strategy for OP Stack chains (Optimism, Base, Unichain, etc)","version":1}},"Registry":{"abi":[{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ChainAlreadyExists","type":"error"},{"inputs":[],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidBufferMultiple","type":"error"},{"inputs":[],"name":"InvalidCollateralFactor","type":"error"},{"inputs":[],"name":"InvalidInitialMarginsClamps","type":"error"},{"inputs":[],"name":"InvalidInitialMarginsConfiguration","type":"error"},{"inputs":[],"name":"InvalidInitialMarginsFactors","type":"error"},{"inputs":[],"name":"InvalidInterestKinks","type":"error"},{"inputs":[],"name":"InvalidLiabilityFactor","type":"error"},{"inputs":[],"name":"InvalidMaxFundingRate","type":"error"},{"inputs":[],"name":"InvalidMaxUtilizationRate","type":"error"},{"inputs":[],"name":"InvalidRateInterestKinks","type":"error"},{"inputs":[],"name":"InvalidUSDInterestKinks","type":"error"},{"inputs":[],"name":"InvalidUSDRateInterestKinks","type":"error"},{"inputs":[],"name":"InvalidUtilizationCap","type":"error"},{"inputs":[{"internalType":"uint16","name":"asset","type":"uint16"}],"name":"NoPendingRiskParameters","type":"error"},{"inputs":[],"name":"NotAdmin","type":"error"},{"inputs":[],"name":"NotRiskManager","type":"error"},{"inputs":[],"name":"RiskManagerNotSet","type":"error"},{"inputs":[{"internalType":"uint16","name":"asset","type":"uint16"},{"internalType":"uint256","name":"eligibleAt","type":"uint256"}],"name":"TooSoon","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint64","name":"routingId","type":"uint64"},{"internalType":"uint64","name":"vmId","type":"uint64"}],"indexed":false,"internalType":"struct Registry.ChainId","name":"chain","type":"tuple"},{"indexed":false,"internalType":"uint16","name":"index","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"current","type":"uint256"}],"name":"Max1HrDepositChanged","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint64","name":"routingId","type":"uint64"},{"internalType":"uint64","name":"vmId","type":"uint64"}],"indexed":false,"internalType":"struct Registry.ChainId","name":"chain","type":"tuple"},{"indexed":false,"internalType":"uint16","name":"index","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"current","type":"uint256"}],"name":"MaxDepositChanged","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint64","name":"routingId","type":"uint64"},{"internalType":"uint64","name":"vmId","type":"uint64"}],"indexed":false,"internalType":"struct Registry.ChainId","name":"chain","type":"tuple"},{"indexed":false,"internalType":"uint16","name":"index","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"current","type":"uint256"}],"name":"MinWeightChanged","type":"event"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"index","type":"uint16"}],"name":"applyPendingRiskParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeAccount","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"routingId","type":"uint64"},{"internalType":"uint64","name":"vmId","type":"uint64"}],"internalType":"struct Registry.ChainId","name":"chainId","type":"tuple"},{"internalType":"uint16","name":"index","type":"uint16"}],"name":"getAssetData","outputs":[{"components":[{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"bytes32","name":"assetAddress","type":"bytes32"},{"components":[{"internalType":"uint64","name":"routingId","type":"uint64"},{"internalType":"uint64","name":"vmId","type":"uint64"}],"internalType":"struct Registry.ChainId","name":"chainId","type":"tuple"},{"internalType":"uint256","name":"maxDeposits","type":"uint256"},{"internalType":"uint256","name":"max1hrDeposits","type":"uint256"},{"internalType":"uint256","name":"minWeight","type":"uint256"}],"internalType":"struct Registry.AssetData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"routingId","type":"uint64"},{"internalType":"uint64","name":"vmId","type":"uint64"}],"internalType":"struct Registry.ChainId","name":"chainId","type":"tuple"},{"internalType":"bytes32","name":"assetAddress","type":"bytes32"}],"name":"getAssetIndex","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"start","type":"uint16"},{"internalType":"uint16","name":"end","type":"uint16"}],"name":"getAssets","outputs":[{"components":[{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"bytes32","name":"assetAddress","type":"bytes32"},{"components":[{"internalType":"uint64","name":"routingId","type":"uint64"},{"internalType":"uint64","name":"vmId","type":"uint64"}],"internalType":"struct Registry.ChainId","name":"chainId","type":"tuple"},{"internalType":"uint256","name":"maxDeposits","type":"uint256"},{"internalType":"uint256","name":"max1hrDeposits","type":"uint256"},{"internalType":"uint256","name":"minWeight","type":"uint256"}],"internalType":"struct Registry.AssetData[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"start","type":"uint16"},{"internalType":"uint16","name":"end","type":"uint16"}],"name":"getRiskParameters","outputs":[{"components":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxSpotOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxUtilization","type":"uint256"},{"internalType":"bool","name":"isolatedOnly","type":"bool"},{"internalType":"uint256[]","name":"interestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"kinkInterestRates","type":"uint256[]"},{"internalType":"uint256[]","name":"usdInterestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"usdKinkInterestRates","type":"uint256[]"},{"internalType":"uint256","name":"skewModifier","type":"uint256"},{"internalType":"uint256","name":"skewCliff","type":"uint256"},{"internalType":"int256","name":"baseFundingRate","type":"int256"},{"internalType":"uint256","name":"premiumClamp","type":"uint256"},{"internalType":"uint256[]","name":"initialMarginClamps","type":"uint256[]"},{"internalType":"uint256[]","name":"initialMarginFactors","type":"uint256[]"},{"internalType":"uint256","name":"maxFundingRate","type":"uint256"},{"internalType":"uint256","name":"maxUtilizationRate","type":"uint256"},{"internalType":"uint256","name":"bufferMultiple","type":"uint256"}],"internalType":"struct Registry.RiskParameters[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"pendingRiskParameters","outputs":[{"components":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxSpotOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxUtilization","type":"uint256"},{"internalType":"bool","name":"isolatedOnly","type":"bool"},{"internalType":"uint256[]","name":"interestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"kinkInterestRates","type":"uint256[]"},{"internalType":"uint256[]","name":"usdInterestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"usdKinkInterestRates","type":"uint256[]"},{"internalType":"uint256","name":"skewModifier","type":"uint256"},{"internalType":"uint256","name":"skewCliff","type":"uint256"},{"internalType":"int256","name":"baseFundingRate","type":"int256"},{"internalType":"uint256","name":"premiumClamp","type":"uint256"},{"internalType":"uint256[]","name":"initialMarginClamps","type":"uint256[]"},{"internalType":"uint256[]","name":"initialMarginFactors","type":"uint256[]"},{"internalType":"uint256","name":"maxFundingRate","type":"uint256"},{"internalType":"uint256","name":"maxUtilizationRate","type":"uint256"},{"internalType":"uint256","name":"bufferMultiple","type":"uint256"}],"internalType":"struct Registry.RiskParameters","name":"parameters","type":"tuple"},{"internalType":"uint256","name":"validAfter","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"riskManagerMultisig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"riskParameterChangeDelaySeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"riskParameters","outputs":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxSpotOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxUtilization","type":"uint256"},{"internalType":"bool","name":"isolatedOnly","type":"bool"},{"internalType":"uint256","name":"skewModifier","type":"uint256"},{"internalType":"uint256","name":"skewCliff","type":"uint256"},{"internalType":"int256","name":"baseFundingRate","type":"int256"},{"internalType":"uint256","name":"premiumClamp","type":"uint256"},{"internalType":"uint256","name":"maxFundingRate","type":"uint256"},{"internalType":"uint256","name":"maxUtilizationRate","type":"uint256"},{"internalType":"uint256","name":"bufferMultiple","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"bytes32","name":"assetAddress","type":"bytes32"},{"components":[{"internalType":"uint64","name":"routingId","type":"uint64"},{"internalType":"uint64","name":"vmId","type":"uint64"}],"internalType":"struct Registry.ChainId","name":"chainId","type":"tuple"},{"internalType":"uint256","name":"maxDeposits","type":"uint256"},{"internalType":"uint256","name":"max1hrDeposits","type":"uint256"},{"internalType":"uint256","name":"minWeight","type":"uint256"}],"internalType":"struct Registry.AssetData","name":"data","type":"tuple"}],"name":"setAssetData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"account","type":"bytes32"}],"name":"setFeeAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"routingId","type":"uint64"},{"internalType":"uint64","name":"vmId","type":"uint64"}],"internalType":"struct Registry.ChainId","name":"chainId","type":"tuple"},{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"uint256","name":"newMaxDeposit","type":"uint256"}],"name":"setMax1HrDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"routingId","type":"uint64"},{"internalType":"uint64","name":"vmId","type":"uint64"}],"internalType":"struct Registry.ChainId","name":"chainId","type":"tuple"},{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"uint256","name":"newMaxDeposit","type":"uint256"}],"name":"setMaxDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"routingId","type":"uint64"},{"internalType":"uint64","name":"vmId","type":"uint64"}],"internalType":"struct Registry.ChainId","name":"chain","type":"tuple"},{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"uint256","name":"newMinWeight","type":"uint256"}],"name":"setMinWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"index","type":"uint16"},{"components":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxSpotOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxUtilization","type":"uint256"},{"internalType":"bool","name":"isolatedOnly","type":"bool"},{"internalType":"uint256[]","name":"interestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"kinkInterestRates","type":"uint256[]"},{"internalType":"uint256[]","name":"usdInterestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"usdKinkInterestRates","type":"uint256[]"},{"internalType":"uint256","name":"skewModifier","type":"uint256"},{"internalType":"uint256","name":"skewCliff","type":"uint256"},{"internalType":"int256","name":"baseFundingRate","type":"int256"},{"internalType":"uint256","name":"premiumClamp","type":"uint256"},{"internalType":"uint256[]","name":"initialMarginClamps","type":"uint256[]"},{"internalType":"uint256[]","name":"initialMarginFactors","type":"uint256[]"},{"internalType":"uint256","name":"maxFundingRate","type":"uint256"},{"internalType":"uint256","name":"maxUtilizationRate","type":"uint256"},{"internalType":"uint256","name":"bufferMultiple","type":"uint256"}],"internalType":"struct Registry.RiskParameters","name":"parameters","type":"tuple"}],"name":"setPendingRiskParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"multisig","type":"address"}],"name":"setRiskManagerMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"collateralFactor","type":"uint8"},{"internalType":"uint8","name":"liabilityFactor","type":"uint8"},{"internalType":"uint256","name":"maxCollateral","type":"uint256"},{"internalType":"uint256","name":"maxOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxSpotOpenInterest","type":"uint256"},{"internalType":"uint256","name":"maxUtilization","type":"uint256"},{"internalType":"bool","name":"isolatedOnly","type":"bool"},{"internalType":"uint256[]","name":"interestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"kinkInterestRates","type":"uint256[]"},{"internalType":"uint256[]","name":"usdInterestKinks","type":"uint256[]"},{"internalType":"uint256[]","name":"usdKinkInterestRates","type":"uint256[]"},{"internalType":"uint256","name":"skewModifier","type":"uint256"},{"internalType":"uint256","name":"skewCliff","type":"uint256"},{"internalType":"int256","name":"baseFundingRate","type":"int256"},{"internalType":"uint256","name":"premiumClamp","type":"uint256"},{"internalType":"uint256[]","name":"initialMarginClamps","type":"uint256[]"},{"internalType":"uint256[]","name":"initialMarginFactors","type":"uint256[]"},{"internalType":"uint256","name":"maxFundingRate","type":"uint256"},{"internalType":"uint256","name":"maxUtilizationRate","type":"uint256"},{"internalType":"uint256","name":"bufferMultiple","type":"uint256"}],"internalType":"struct Registry.RiskParameters","name":"params","type":"tuple"}],"name":"validateRiskParameters","outputs":[],"stateMutability":"pure","type":"function"}],"contractName":"Registry","deploymentBytecode":{"bytecode":"0x608034607657601f6122e038819003918201601f19168301916001600160401b03831184841017607a57808492602094604052833981010312607657516001600160a01b03811690819003607657620151806002555f80546001600160a01b031916919091179055604051612251908161008f8239f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f3560e01c90816304cd46f91461115d575080630cb661c7146110e4578063114bb9c5146110165780632491905014610f655780633a076ddd14610ec05780634ffcbdfb14610e6d578063525ea8b714610e455780635799026114610e0b57806365e17c9d14610dee578063698670e314610dba5780636cbb0b54146109d5578063704b6c0214610951578063a7b7b47014610858578063a812e22414610801578063af8c83381461074b578063b4bb064614610418578063bc67a603146101ec578063e2a0a600146101b3578063f0fef575146101235763f851a440146100f8575f80fd5b3461011f575f36600319011261011f575f546040516001600160a01b039091168152602090f35b5f80fd5b3461011f57604036600319011261011f5761014d61013f611177565b610147611188565b90611f7c565b6040518091602082016020835281518091526040830190602060408260051b8601019301915f905b82821061018457505050500390f35b919360019193955060206101a38192603f198a82030186528851611643565b9601920192018594939192610175565b3461011f57602036600319011261011f576001546001600160a01b031633036101de57600435600755005b6206732360e51b5f5260045ffd5b3461011f5760e036600319011261011f5760405161020981611230565b610211611177565b815260208101906024358252604060431936011261011f576040519161023683611215565b6044356001600160401b038116810361011f5783526064356001600160401b038116810361011f5760208401526040820192835260608201916084358352608081019160a435835260a0820160c435815260018060a01b036001541633036101de5761ffff83511660055410610409578151156103fa5761ffff8351165f52600660205260405f20938651966001600160401b036020818a511699015116936001600160401b0389165f528660205260405f206001600160401b0386165f52602052600160405f2001546103eb5760059460018801976001600160401b038954159b165f526020526001600160401b0360405f2091165f5260205261ffff60405f2096511661ffff19875416178655516001860155519561035a8760028701611e68565b516003850155516004840155519101558054600160401b8110156103d75761038791600182018155611844565b9190916103c45761039791611e68565b61039d57005b600554600181018091116103b057600555005b634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f525f60045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b6329409fff60e01b5f5260045ffd5b63d92e233d60e01b5f5260045ffd5b634e23d03560e01b5f5260045ffd5b3461011f57604036600319011261011f57610431611177565b6024356001600160401b03811161011f5761045090369060040161130a565b6001549091906001600160a01b031633036101de5761047861ffff6005549216918210611b00565b61048182611b8d565b61048d60025442611796565b906040519261049b84611215565b8352602083019182525f52600360205260405f20915160ff81511683549061ff00602084015160081b169161ffff19161717835560408101516001840155606081015160028401556080810151600384015560a081015160048401556005830160c0820151151560ff801983541691161790556006830160e0820151908151916001600160401b0383116103d7576020906105368484611e28565b01905f5260205f205f5b838110610737575050505060078301610100820151908151916001600160401b0383116103d7576020906105748484611e28565b01905f5260205f205f5b838110610723575050505060088301610120820151908151916001600160401b0383116103d7576020906105b28484611e28565b01905f5260205f205f5b83811061070f575050505060098301610140820151908151916001600160401b0383116103d7576020906105f08484611e28565b01905f5260205f205f5b8381106106fb5750505050610160810151600a840155610180810151600b8401556101a0810151600c8401556101c0810151600d840155600e83016101e0820151908151916001600160401b0383116103d75760209061065a8484611e28565b01905f5260205f205f5b8381106106e75750505050600f8301610200820151908151916001600160401b0383116103d7576020906106988484611e28565b01905f5260205f205f5b8381106106d35761022085015160108801556102408501516011880155610260850151601288015585516013880155005b6001906020845194019381840155016106a2565b600190602084519401938184015501610664565b6001906020845194019381840155016105fa565b6001906020845194019381840155016105bc565b60019060208451940193818401550161057e565b600190602084519401938184015501610540565b3461011f57610759366111ea565b6001549092906001600160a01b031633036101de576107fc7f9b0a62bc173ccdd4228691d9af5cbe894061fb605491498f20216dc69fdcee1e936005546107a661ffff8616918210611b00565b6107af84611b35565b6107bb60208601611b35565b5f9283526006602090815260408085206001600160401b03948516865282528085209290931684525290819020600401805490839055905194859485611b49565b0390a1005b3461011f57602036600319011261011f5761ffff61081d611177565b165f52600360205261084e60405f206013610837826114ff565b910154604051928392604084526040840190611643565b9060208301520390f35b3461011f57610866366111ea565b6001549092906001600160a01b031633036101de576107fc7f61add8ab6aedaf5e8c15fd0f3b5dc7239de9517bae157dc6f09438d619959a5b936005546108b361ffff8616918210611b00565b805f52600660205260405f206001600160401b036108d086611b35565b165f5260205260405f2060208501906001600160401b036108f083611b35565b165f52602052600560405f200154915f52600660205260405f206001600160401b0361091b87611b35565b165f526020526001600160401b0361093660405f2092611b35565b165f5260205281600560405f20015560405194859485611b49565b3461011f57602036600319011261011f576004356001600160a01b0381169081900361011f575f546001600160a01b03811633036109c6578115806109b3575b6109a4576001600160a01b031916175f55005b632b47857560e01b5f5260045ffd5b506001546001600160a01b031615610991565b637bfa4b9f60e01b5f5260045ffd5b3461011f57602036600319011261011f576109ee611177565b610a0161ffff6005549216918210611b00565b805f52600360205260405f20601360405191610a1c83611215565b610a25816114ff565b83520154602082019080825215610da7575142811015610d91575051610a4a81611b8d565b815f52600460205260405f209060ff81511682549061ff00602084015160081b169161ffff19161717825560408101516001830155606081015160028301556080810151600383015560a081015160048301556005820160c0820151151560ff801983541691161790556006820160e0820151908151916001600160401b0383116103d757602090610adc8484611e28565b01905f5260205f205f5b838110610d7d575050505060078201610100820151908151916001600160401b0383116103d757602090610b1a8484611e28565b01905f5260205f205f5b838110610d69575050505060088201610120820151908151916001600160401b0383116103d757602090610b588484611e28565b01905f5260205f205f5b838110610d55575050505060098201610140820151908151916001600160401b0383116103d757602090610b968484611e28565b01905f5260205f205f5b838110610d415750505050610160810151600a830155610180810151600b8301556101a0810151600c8301556101c0810151600d830155600e82016101e0820151908151916001600160401b0383116103d757602090610c008484611e28565b01905f5260205f205f5b838110610d2d5750505050600f8201610200820151908151916001600160401b0383116103d757602090610c3e8484611e28565b01905f5260205f205f5b838110610d195786866012610260886102208101516010850155610240810151601185015501519101555f5260036020525f601360408220828155826001820155826002820155826003820155826004820155826005820155610cad60068201611df8565b610cb960078201611df8565b610cc560088201611df8565b610cd160098201611df8565b82600a82015582600b82015582600c82015582600d820155610cf5600e8201611df8565b610d01600f8201611df8565b82601082015582601182015582601282015501555f80f35b600190602084519401938184015501610c48565b600190602084519401938184015501610c0a565b600190602084519401938184015501610ba0565b600190602084519401938184015501610b62565b600190602084519401938184015501610b24565b600190602084519401938184015501610ae6565b82636bfedefd60e11b5f5260045260245260445ffd5b8263193e674760e21b5f5260045260245ffd5b3461011f5736600319016060811261011f5760401361011f576020610de0604435611d61565b63ffffffff60405191168152f35b3461011f575f36600319011261011f576020600754604051908152f35b3461011f57602036600319011261011f576004356001600160401b03811161011f57610e3e610e4391369060040161130a565b611b8d565b005b3461011f575f36600319011261011f576001546040516001600160a01b039091168152602090f35b3461011f57602036600319011261011f576004356001600160a01b0381169081900361011f575f546001600160a01b031633036109c6576bffffffffffffffffffffffff60a01b60015416176001555f80f35b3461011f5736600319016060811261011f5760401361011f5760443561ffff811680910361011f57610ef06117a3565b505f52600660205260405f206004356001600160401b038116810361011f57806001600160401b039150165f5260205260405f206024356001600160401b038116810361011f57806001600160401b039150165f5260205260e0610f5660405f20611881565b610f636040518092611199565bf35b3461011f57610f73366111ea565b6001549092906001600160a01b031633036101de576107fc7f35095f4ef942f9cb4170d9a93adc7fe9ebc8faf2df4a91b87b0dced92784718f93600554610fc061ffff8616918210611b00565b610fc984611b35565b610fd560208601611b35565b5f9283526006602090815260408085206001600160401b03948516865282528085209290931684525290819020600301805490839055905194859485611b49565b3461011f57602036600319011261011f5761ffff611032611177565b165f5260046020526101c060ff60405f20805490600181015460028201546003830154600484015486600586015416600a86015490600b87015492600c88015494600d8901549660108a015498601260118c01549b01549b60206040519e8f92818116845260081c1691015260408d015260608c015260808b015260a08a0152151560c089015260e08801526101008701526101208601526101408501526101608401526101808301526101a0820152f35b3461011f57604036600319011261011f5761110e611100611177565b611108611188565b906118ed565b6040518091602082016020835281518091526020604084019201905f5b818110611139575050500390f35b91935091602060e08261114f6001948851611199565b01940191019184939261112b565b3461011f575f36600319011261011f576020906002548152f35b6004359061ffff8216820361011f57565b6024359061ffff8216820361011f57565b60a060c09161ffff8151168452602081015160208501526001600160401b03602060408301518281511660408801520151166060850152606081015160808501526080810151828501520151910152565b600319016080811261011f5760401361011f5760049060443561ffff8116810361011f579060643590565b604081019081106001600160401b038211176103d757604052565b60c081019081106001600160401b038211176103d757604052565b61028081019081106001600160401b038211176103d757604052565b90601f801991011681019081106001600160401b038211176103d757604052565b359060ff8216820361011f57565b6001600160401b0381116103d75760051b60200190565b9080601f8301121561011f5781356112c481611296565b926112d26040519485611267565b81845260208085019260051b82010192831161011f57602001905b8282106112fa5750505090565b81358152602091820191016112ed565b9190916102808184031261011f57604051906113258261124b565b819361133082611288565b835261133e60208301611288565b602084015260408201356040840152606082013560608401526080820135608084015260a082013560a084015260c0820135801515810361011f5760c084015260e08201356001600160401b03811161011f578161139d9184016112ad565b60e08401526101008201356001600160401b03811161011f57816113c29184016112ad565b6101008401526101208201356001600160401b03811161011f57816113e89184016112ad565b6101208401526101408201356001600160401b03811161011f578161140e9184016112ad565b6101408401526101608201356101608401526101808201356101808401526101a08201356101a08401526101c08201356101c08401526101e08201356001600160401b03811161011f57816114649184016112ad565b6101e0840152610200820135916001600160401b03831161011f576114906102609392849383016112ad565b6102008501526102208101356102208501526102408101356102408501520135910152565b90604051918281549182825260208201905f5260205f20925f5b8181106114e65750506114e492500383611267565b565b84548352600194850194879450602090930192016114cf565b9060405161150c8161124b565b6102606012829460ff8154818116865260081c166020850152600181015460408501526002810154606085015260038101546080850152600481015460a085015260ff600582015416151560c0850152611568600682016114b5565b60e0850152611579600782016114b5565b61010085015261158b600882016114b5565b61012085015261159d600982016114b5565b610140850152600a810154610160850152600b810154610180850152600c8101546101a0850152600d8101546101c08501526115db600e82016114b5565b6101e08501526115ed600f82016114b5565b610200850152601081015461022085015260118101546102408501520154910152565b90602080835192838152019201905f5b81811061162d5750505090565b8251845260209384019390920191600101611620565b9060ff825116815260ff602083015116602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015260c0820151151560c08201526102608061174e61173a6116f66116e26116ce6116ba60e08a015161028060e08b01526102808a0190611610565b6101008a01518982036101008b0152611610565b6101208901518882036101208a0152611610565b610140880151878203610140890152611610565b6101608701516101608701526101808701516101808701526101a08701516101a08701526101c08701516101c08701526101e08701518682036101e0880152611610565b610200860151858203610200870152611610565b93610220810151610220850152610240810151610240850152015191015290565b35906001600160401b038216820361011f57565b61ffff1661ffff81146103b05760010190565b919082018092116103b057565b604051906117b082611230565b5f60a0838281528260208201526040516117c981611215565b83815283602082015260408201528260608201528260808201520152565b604051906117f6602083611267565b5f80835282815b82811061180957505050565b6020906118146117a3565b828285010152016117fd565b9061ffff8091169116039061ffff82116103b057565b5f1981146103b05760010190565b8054821015611859575f5260205f2001905f90565b634e487b7160e01b5f52603260045260245ffd5b80518210156118595760209160051b010190565b9060405161188e81611230565b60a06005829461ffff8154168452600181015460208501526040516118b281611215565b6001600160401b036002830154818116835260401c166020820152604085015260038101546060850152600481015460808501520154910152565b6005545f9290835b61ffff85168281101561192b576119259161191f915f526006602052600160405f20015490611796565b94611783565b936118f5565b5093509193909361ffff81169380851015611ae3578061ffff871611611af4575b5061ffff851694848610611ae35761ffff9161196c919693959496611820565b1661197681611296565b916119846040519384611267565b818352601f1961199383611296565b015f5b818110611ac05750505f905f945f5b61ffff811689811080611ab7575b15611aab575f52600660205260405f209460018601948554995f915b8b831080611aa2575b15611a85578581101580611a7c575b611a04575b6119f86119fe91611836565b92611836565b916119cf565b611a0e8389611844565b50546001600160401b0381166001600160401b03165f528960205260405f209060401c6001600160401b03166001600160401b03165f5260205260405f209a80611a5790611836565b9b611a6190611881565b611a6b828d61186d565b52611a76908b61186d565b506119ec565b508681106119e7565b9b9497509550509750611a9790611783565b9792969390976119a5565b50838b106119d8565b50949750505050505050565b508588106119b3565b602090611ad19896949793986117a3565b82828801015201969195929496611996565b505092505050611af16117e7565b90565b61ffff1694505f61194c565b15611b0757565b60405162461bcd60e51b815260206004820152600660248201526508585cdcd95d60d21b6044820152606490fd5b356001600160401b038116810361011f5790565b9094939261ffff6080936001600160401b03611b78602060a087019a83611b6f8261176f565b1688520161176f565b16602085015216604083015260608201520152565b606460ff82511611611d5257606460ff60208301511611611d4357670de0b6b3a764000060a082015111611d345761047661022082015111611d255761047661024082015111611d1657610260810151620f42408110908115611d09575b50611cfa5760e08101611bfe8151612108565b15611ceb57611c0d9051612180565b15611ceb576101208101611c218151612108565b15611cdc57611c309051612180565b15611cdc57611c436101008201516121b0565b15611ccd57611c566101408201516121b0565b15611cbe576101e0810161020081515192019182515103611caf57611c7b9051612108565b15611ca057611c8a90516121e4565b15611c9157565b637015a03b60e01b5f5260045ffd5b6329f7281b60e21b5f5260045ffd5b63bfa51ee360e01b5f5260045ffd5b635646ba3b60e11b5f5260045ffd5b630adc448560e21b5f5260045ffd5b630376a9ef60e31b5f5260045ffd5b6365c991a560e01b5f5260045ffd5b63adb838cd60e01b5f5260045ffd5b621e84809150115f611beb565b6328be116d60e21b5f5260045ffd5b63076eb25360e11b5f5260045ffd5b63cc15654960e01b5f5260045ffd5b632a7f863d60e21b5f5260045ffd5b6302f22cad60e61b5f5260045ffd5b6004356001600160401b038116810361011f57602435916001600160401b038316830361011f575f6001600160401b038060055494169416905b61ffff811684811015611dea57805f52600660205260405f20865f5260205260405f20835f52602052600160405f2001548414611de15750611ddc90611783565b611d9b565b94505050505090565b50505050505063ffffffff90565b8054905f815581611e07575050565b5f5260205f20908101905b818110611e1d575050565b5f8155600101611e12565b90600160401b81116103d757815491818155828210611e4657505050565b5f5260205f2091820191015b818110611e5d575050565b5f8155600101611e52565b906001600160401b038151166fffffffffffffffff00000000000000006020845493836001600160401b03198616178655015160401b16916fffffffffffffffffffffffffffffffff191617179055565b60405190611ec8602083611267565b5f80835282815b828110611edb57505050565b602090604051611eea8161124b565b5f81525f838201525f60408201525f60608201525f60808201525f60a08201525f60c0820152606060e08201526060610100820152606061012082015260606101408201525f6101608201525f6101808201525f6101a08201525f6101c082015260606101e082015260606102008201525f6102208201525f6102408201525f61026082015282828501015201611ecf565b60055461ffff80831694939116808510156120fb578061ffff8316116120f3575b508361ffff8216106120e75761ffff91611fb691611820565b16611fc081611296565b92611fce6040519485611267565b818452601f19611fdd83611296565b015f5b8181106120465750505f5b61ffff811690838210156120405781830161ffff81116103b05761203b9261ffff61203592165f52600460205261202460405f206114ff565b61202e828a61186d565b528761186d565b50611783565b611feb565b50505050565b6020906040516120558161124b565b5f81525f838201525f60408201525f60608201525f60808201525f60a08201525f60c0820152606060e08201526060610100820152606061012082015260606101408201525f6101608201525f6101808201525f6101a08201525f6101c082015260606101e082015260606102008201525f6102208201525f6102408201525f61026082015282828901015201611fe0565b50509050611af1611eb9565b90505f611f9d565b5050509050611af1611eb9565b8051905f908215801561216c575b612165575f915b83831061212d5750505050600190565b612137838361186d565b5190620f4240821161215c5781106121545760019092019161211d565b505050505f90565b50505050505f90565b5050505f90565b508051156118595760208101511515612116565b8051801515918261219057505090565b5f19820192509082116103b057620f4240916121ab9161186d565b511490565b8051905f90815b8383106121c75750505050600190565b6121d1838361186d565b51908110612154576001909201916121b7565b8051905f90620f423f5b8383106121fe5750505050600190565b612208838361186d565b51908111612154576001909201916121ee56fea26469706673582212201a0e5b061dbc5669db9937ab714356062c9af05eea7b1d4bb9eeaf0073ef81fe64736f6c634300081e0033"},"devdoc":{"details":"Uses admin and multisig roles to control sensitive operations like asset registration and risk configuration.","kind":"dev","methods":{"applyPendingRiskParameters(uint16)":{"details":"Reverts with `\"!asset\"` if index >= assets.count.Reverts with `NoPendingRiskParameters` if there are no pending risk parameters for the specified assetReverts with `TooSoon` if the pending risk parameters are not yet eligible","params":{"index":"The asset index."}},"constructor":{"details":"Sets the deployer as the initial admin.","params":{"_admin":"The admin controller of the vault."}},"getAssetData((uint64,uint64),uint16)":{"params":{"chainId":"the chain ID to query.","index":"The asset index to query."},"returns":{"_0":"The corresponding AssetData struct."}},"getAssetIndex((uint64,uint64),bytes32)":{"params":{"assetAddress":"The asset address (as bytes32).","chainId":"The chain ID to search."},"returns":{"_0":"The index of the asset, or `type(uint32).max` if not found."}},"getAssets(uint16,uint16)":{"params":{"end":"The end index (not-inclusive).","start":"The start index (inclusive)."},"returns":{"_0":"An array of AssetData structs."}},"getRiskParameters(uint16,uint16)":{"params":{"end":"The end index (not inclusive).","start":"The start index (inclusive)."},"returns":{"_0":"An array of RiskParameters."}},"setAdmin(address)":{"details":"Reverts with `NotAdmin`; Only the admin can set a new admin.The new administrator address is allowed to be the null address. Setting the administrator to this address disables administration of the registry contract.","params":{"newAdmin":"The new admin address."}},"setAssetData((uint16,bytes32,(uint64,uint64),uint256,uint256,uint256))":{"details":"Automatically adds new assets or chain instances if not already present.Reverts with `NotRiskManager`; Only the risk manager can set asset data.","params":{"data":"The chain-specific asset data."}},"setPendingRiskParameters(uint16,(uint8,uint8,uint256,uint256,uint256,uint256,bool,uint256[],uint256[],uint256[],uint256[],uint256,uint256,int256,uint256,uint256[],uint256[],uint256,uint256,uint256))":{"details":"Reverts with `NotRiskManager`; Only the risk manager can set risk parameters.Reverts with `\"!asset\"` if index >= assets.count.","params":{"index":"The asset index.","parameters":"The risk parameters to set"}},"setRiskManagerMultisig(address)":{"details":"Reverts with `NotAdmin`; Only the admin can set a risk manager.","params":{"multisig":"The new address to set."}}},"title":"Registry","version":1},"methodIdentifiers":{"admin()":"0xf851a440","applyPendingRiskParameters(uint16)":"0x6cbb0b54","feeAccount()":"0x65e17c9d","getAssetData((uint64,uint64),uint16)":"0x3a076ddd","getAssetIndex((uint64,uint64),bytes32)":"0x698670e3","getAssets(uint16,uint16)":"0x0cb661c7","getRiskParameters(uint16,uint16)":"0xf0fef575","pendingRiskParameters(uint16)":"0xa812e224","riskManagerMultisig()":"0x525ea8b7","riskParameterChangeDelaySeconds()":"0x04cd46f9","riskParameters(uint16)":"0x114bb9c5","setAdmin(address)":"0x704b6c02","setAssetData((uint16,bytes32,(uint64,uint64),uint256,uint256,uint256))":"0xbc67a603","setFeeAccount(bytes32)":"0xe2a0a600","setMax1HrDeposits((uint64,uint64),uint16,uint256)":"0xaf8c8338","setMaxDeposits((uint64,uint64),uint16,uint256)":"0x24919050","setMinWeight((uint64,uint64),uint16,uint256)":"0xa7b7b470","setPendingRiskParameters(uint16,(uint8,uint8,uint256,uint256,uint256,uint256,bool,uint256[],uint256[],uint256[],uint256[],uint256,uint256,int256,uint256,uint256[],uint256[],uint256,uint256,uint256))":"0xb4bb0646","setRiskManagerMultisig(address)":"0x4ffcbdfb","validateRiskParameters((uint8,uint8,uint256,uint256,uint256,uint256,bool,uint256[],uint256[],uint256[],uint256[],uint256,uint256,int256,uint256,uint256[],uint256[],uint256,uint256,uint256))":"0x57990261"},"runtimeBytecode":{"bytecode":"0x6080806040526004361015610012575f80fd5b5f3560e01c90816304cd46f91461115d575080630cb661c7146110e4578063114bb9c5146110165780632491905014610f655780633a076ddd14610ec05780634ffcbdfb14610e6d578063525ea8b714610e455780635799026114610e0b57806365e17c9d14610dee578063698670e314610dba5780636cbb0b54146109d5578063704b6c0214610951578063a7b7b47014610858578063a812e22414610801578063af8c83381461074b578063b4bb064614610418578063bc67a603146101ec578063e2a0a600146101b3578063f0fef575146101235763f851a440146100f8575f80fd5b3461011f575f36600319011261011f575f546040516001600160a01b039091168152602090f35b5f80fd5b3461011f57604036600319011261011f5761014d61013f611177565b610147611188565b90611f7c565b6040518091602082016020835281518091526040830190602060408260051b8601019301915f905b82821061018457505050500390f35b919360019193955060206101a38192603f198a82030186528851611643565b9601920192018594939192610175565b3461011f57602036600319011261011f576001546001600160a01b031633036101de57600435600755005b6206732360e51b5f5260045ffd5b3461011f5760e036600319011261011f5760405161020981611230565b610211611177565b815260208101906024358252604060431936011261011f576040519161023683611215565b6044356001600160401b038116810361011f5783526064356001600160401b038116810361011f5760208401526040820192835260608201916084358352608081019160a435835260a0820160c435815260018060a01b036001541633036101de5761ffff83511660055410610409578151156103fa5761ffff8351165f52600660205260405f20938651966001600160401b036020818a511699015116936001600160401b0389165f528660205260405f206001600160401b0386165f52602052600160405f2001546103eb5760059460018801976001600160401b038954159b165f526020526001600160401b0360405f2091165f5260205261ffff60405f2096511661ffff19875416178655516001860155519561035a8760028701611e68565b516003850155516004840155519101558054600160401b8110156103d75761038791600182018155611844565b9190916103c45761039791611e68565b61039d57005b600554600181018091116103b057600555005b634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f525f60045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b6329409fff60e01b5f5260045ffd5b63d92e233d60e01b5f5260045ffd5b634e23d03560e01b5f5260045ffd5b3461011f57604036600319011261011f57610431611177565b6024356001600160401b03811161011f5761045090369060040161130a565b6001549091906001600160a01b031633036101de5761047861ffff6005549216918210611b00565b61048182611b8d565b61048d60025442611796565b906040519261049b84611215565b8352602083019182525f52600360205260405f20915160ff81511683549061ff00602084015160081b169161ffff19161717835560408101516001840155606081015160028401556080810151600384015560a081015160048401556005830160c0820151151560ff801983541691161790556006830160e0820151908151916001600160401b0383116103d7576020906105368484611e28565b01905f5260205f205f5b838110610737575050505060078301610100820151908151916001600160401b0383116103d7576020906105748484611e28565b01905f5260205f205f5b838110610723575050505060088301610120820151908151916001600160401b0383116103d7576020906105b28484611e28565b01905f5260205f205f5b83811061070f575050505060098301610140820151908151916001600160401b0383116103d7576020906105f08484611e28565b01905f5260205f205f5b8381106106fb5750505050610160810151600a840155610180810151600b8401556101a0810151600c8401556101c0810151600d840155600e83016101e0820151908151916001600160401b0383116103d75760209061065a8484611e28565b01905f5260205f205f5b8381106106e75750505050600f8301610200820151908151916001600160401b0383116103d7576020906106988484611e28565b01905f5260205f205f5b8381106106d35761022085015160108801556102408501516011880155610260850151601288015585516013880155005b6001906020845194019381840155016106a2565b600190602084519401938184015501610664565b6001906020845194019381840155016105fa565b6001906020845194019381840155016105bc565b60019060208451940193818401550161057e565b600190602084519401938184015501610540565b3461011f57610759366111ea565b6001549092906001600160a01b031633036101de576107fc7f9b0a62bc173ccdd4228691d9af5cbe894061fb605491498f20216dc69fdcee1e936005546107a661ffff8616918210611b00565b6107af84611b35565b6107bb60208601611b35565b5f9283526006602090815260408085206001600160401b03948516865282528085209290931684525290819020600401805490839055905194859485611b49565b0390a1005b3461011f57602036600319011261011f5761ffff61081d611177565b165f52600360205261084e60405f206013610837826114ff565b910154604051928392604084526040840190611643565b9060208301520390f35b3461011f57610866366111ea565b6001549092906001600160a01b031633036101de576107fc7f61add8ab6aedaf5e8c15fd0f3b5dc7239de9517bae157dc6f09438d619959a5b936005546108b361ffff8616918210611b00565b805f52600660205260405f206001600160401b036108d086611b35565b165f5260205260405f2060208501906001600160401b036108f083611b35565b165f52602052600560405f200154915f52600660205260405f206001600160401b0361091b87611b35565b165f526020526001600160401b0361093660405f2092611b35565b165f5260205281600560405f20015560405194859485611b49565b3461011f57602036600319011261011f576004356001600160a01b0381169081900361011f575f546001600160a01b03811633036109c6578115806109b3575b6109a4576001600160a01b031916175f55005b632b47857560e01b5f5260045ffd5b506001546001600160a01b031615610991565b637bfa4b9f60e01b5f5260045ffd5b3461011f57602036600319011261011f576109ee611177565b610a0161ffff6005549216918210611b00565b805f52600360205260405f20601360405191610a1c83611215565b610a25816114ff565b83520154602082019080825215610da7575142811015610d91575051610a4a81611b8d565b815f52600460205260405f209060ff81511682549061ff00602084015160081b169161ffff19161717825560408101516001830155606081015160028301556080810151600383015560a081015160048301556005820160c0820151151560ff801983541691161790556006820160e0820151908151916001600160401b0383116103d757602090610adc8484611e28565b01905f5260205f205f5b838110610d7d575050505060078201610100820151908151916001600160401b0383116103d757602090610b1a8484611e28565b01905f5260205f205f5b838110610d69575050505060088201610120820151908151916001600160401b0383116103d757602090610b588484611e28565b01905f5260205f205f5b838110610d55575050505060098201610140820151908151916001600160401b0383116103d757602090610b968484611e28565b01905f5260205f205f5b838110610d415750505050610160810151600a830155610180810151600b8301556101a0810151600c8301556101c0810151600d830155600e82016101e0820151908151916001600160401b0383116103d757602090610c008484611e28565b01905f5260205f205f5b838110610d2d5750505050600f8201610200820151908151916001600160401b0383116103d757602090610c3e8484611e28565b01905f5260205f205f5b838110610d195786866012610260886102208101516010850155610240810151601185015501519101555f5260036020525f601360408220828155826001820155826002820155826003820155826004820155826005820155610cad60068201611df8565b610cb960078201611df8565b610cc560088201611df8565b610cd160098201611df8565b82600a82015582600b82015582600c82015582600d820155610cf5600e8201611df8565b610d01600f8201611df8565b82601082015582601182015582601282015501555f80f35b600190602084519401938184015501610c48565b600190602084519401938184015501610c0a565b600190602084519401938184015501610ba0565b600190602084519401938184015501610b62565b600190602084519401938184015501610b24565b600190602084519401938184015501610ae6565b82636bfedefd60e11b5f5260045260245260445ffd5b8263193e674760e21b5f5260045260245ffd5b3461011f5736600319016060811261011f5760401361011f576020610de0604435611d61565b63ffffffff60405191168152f35b3461011f575f36600319011261011f576020600754604051908152f35b3461011f57602036600319011261011f576004356001600160401b03811161011f57610e3e610e4391369060040161130a565b611b8d565b005b3461011f575f36600319011261011f576001546040516001600160a01b039091168152602090f35b3461011f57602036600319011261011f576004356001600160a01b0381169081900361011f575f546001600160a01b031633036109c6576bffffffffffffffffffffffff60a01b60015416176001555f80f35b3461011f5736600319016060811261011f5760401361011f5760443561ffff811680910361011f57610ef06117a3565b505f52600660205260405f206004356001600160401b038116810361011f57806001600160401b039150165f5260205260405f206024356001600160401b038116810361011f57806001600160401b039150165f5260205260e0610f5660405f20611881565b610f636040518092611199565bf35b3461011f57610f73366111ea565b6001549092906001600160a01b031633036101de576107fc7f35095f4ef942f9cb4170d9a93adc7fe9ebc8faf2df4a91b87b0dced92784718f93600554610fc061ffff8616918210611b00565b610fc984611b35565b610fd560208601611b35565b5f9283526006602090815260408085206001600160401b03948516865282528085209290931684525290819020600301805490839055905194859485611b49565b3461011f57602036600319011261011f5761ffff611032611177565b165f5260046020526101c060ff60405f20805490600181015460028201546003830154600484015486600586015416600a86015490600b87015492600c88015494600d8901549660108a015498601260118c01549b01549b60206040519e8f92818116845260081c1691015260408d015260608c015260808b015260a08a0152151560c089015260e08801526101008701526101208601526101408501526101608401526101808301526101a0820152f35b3461011f57604036600319011261011f5761110e611100611177565b611108611188565b906118ed565b6040518091602082016020835281518091526020604084019201905f5b818110611139575050500390f35b91935091602060e08261114f6001948851611199565b01940191019184939261112b565b3461011f575f36600319011261011f576020906002548152f35b6004359061ffff8216820361011f57565b6024359061ffff8216820361011f57565b60a060c09161ffff8151168452602081015160208501526001600160401b03602060408301518281511660408801520151166060850152606081015160808501526080810151828501520151910152565b600319016080811261011f5760401361011f5760049060443561ffff8116810361011f579060643590565b604081019081106001600160401b038211176103d757604052565b60c081019081106001600160401b038211176103d757604052565b61028081019081106001600160401b038211176103d757604052565b90601f801991011681019081106001600160401b038211176103d757604052565b359060ff8216820361011f57565b6001600160401b0381116103d75760051b60200190565b9080601f8301121561011f5781356112c481611296565b926112d26040519485611267565b81845260208085019260051b82010192831161011f57602001905b8282106112fa5750505090565b81358152602091820191016112ed565b9190916102808184031261011f57604051906113258261124b565b819361133082611288565b835261133e60208301611288565b602084015260408201356040840152606082013560608401526080820135608084015260a082013560a084015260c0820135801515810361011f5760c084015260e08201356001600160401b03811161011f578161139d9184016112ad565b60e08401526101008201356001600160401b03811161011f57816113c29184016112ad565b6101008401526101208201356001600160401b03811161011f57816113e89184016112ad565b6101208401526101408201356001600160401b03811161011f578161140e9184016112ad565b6101408401526101608201356101608401526101808201356101808401526101a08201356101a08401526101c08201356101c08401526101e08201356001600160401b03811161011f57816114649184016112ad565b6101e0840152610200820135916001600160401b03831161011f576114906102609392849383016112ad565b6102008501526102208101356102208501526102408101356102408501520135910152565b90604051918281549182825260208201905f5260205f20925f5b8181106114e65750506114e492500383611267565b565b84548352600194850194879450602090930192016114cf565b9060405161150c8161124b565b6102606012829460ff8154818116865260081c166020850152600181015460408501526002810154606085015260038101546080850152600481015460a085015260ff600582015416151560c0850152611568600682016114b5565b60e0850152611579600782016114b5565b61010085015261158b600882016114b5565b61012085015261159d600982016114b5565b610140850152600a810154610160850152600b810154610180850152600c8101546101a0850152600d8101546101c08501526115db600e82016114b5565b6101e08501526115ed600f82016114b5565b610200850152601081015461022085015260118101546102408501520154910152565b90602080835192838152019201905f5b81811061162d5750505090565b8251845260209384019390920191600101611620565b9060ff825116815260ff602083015116602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015260c0820151151560c08201526102608061174e61173a6116f66116e26116ce6116ba60e08a015161028060e08b01526102808a0190611610565b6101008a01518982036101008b0152611610565b6101208901518882036101208a0152611610565b610140880151878203610140890152611610565b6101608701516101608701526101808701516101808701526101a08701516101a08701526101c08701516101c08701526101e08701518682036101e0880152611610565b610200860151858203610200870152611610565b93610220810151610220850152610240810151610240850152015191015290565b35906001600160401b038216820361011f57565b61ffff1661ffff81146103b05760010190565b919082018092116103b057565b604051906117b082611230565b5f60a0838281528260208201526040516117c981611215565b83815283602082015260408201528260608201528260808201520152565b604051906117f6602083611267565b5f80835282815b82811061180957505050565b6020906118146117a3565b828285010152016117fd565b9061ffff8091169116039061ffff82116103b057565b5f1981146103b05760010190565b8054821015611859575f5260205f2001905f90565b634e487b7160e01b5f52603260045260245ffd5b80518210156118595760209160051b010190565b9060405161188e81611230565b60a06005829461ffff8154168452600181015460208501526040516118b281611215565b6001600160401b036002830154818116835260401c166020820152604085015260038101546060850152600481015460808501520154910152565b6005545f9290835b61ffff85168281101561192b576119259161191f915f526006602052600160405f20015490611796565b94611783565b936118f5565b5093509193909361ffff81169380851015611ae3578061ffff871611611af4575b5061ffff851694848610611ae35761ffff9161196c919693959496611820565b1661197681611296565b916119846040519384611267565b818352601f1961199383611296565b015f5b818110611ac05750505f905f945f5b61ffff811689811080611ab7575b15611aab575f52600660205260405f209460018601948554995f915b8b831080611aa2575b15611a85578581101580611a7c575b611a04575b6119f86119fe91611836565b92611836565b916119cf565b611a0e8389611844565b50546001600160401b0381166001600160401b03165f528960205260405f209060401c6001600160401b03166001600160401b03165f5260205260405f209a80611a5790611836565b9b611a6190611881565b611a6b828d61186d565b52611a76908b61186d565b506119ec565b508681106119e7565b9b9497509550509750611a9790611783565b9792969390976119a5565b50838b106119d8565b50949750505050505050565b508588106119b3565b602090611ad19896949793986117a3565b82828801015201969195929496611996565b505092505050611af16117e7565b90565b61ffff1694505f61194c565b15611b0757565b60405162461bcd60e51b815260206004820152600660248201526508585cdcd95d60d21b6044820152606490fd5b356001600160401b038116810361011f5790565b9094939261ffff6080936001600160401b03611b78602060a087019a83611b6f8261176f565b1688520161176f565b16602085015216604083015260608201520152565b606460ff82511611611d5257606460ff60208301511611611d4357670de0b6b3a764000060a082015111611d345761047661022082015111611d255761047661024082015111611d1657610260810151620f42408110908115611d09575b50611cfa5760e08101611bfe8151612108565b15611ceb57611c0d9051612180565b15611ceb576101208101611c218151612108565b15611cdc57611c309051612180565b15611cdc57611c436101008201516121b0565b15611ccd57611c566101408201516121b0565b15611cbe576101e0810161020081515192019182515103611caf57611c7b9051612108565b15611ca057611c8a90516121e4565b15611c9157565b637015a03b60e01b5f5260045ffd5b6329f7281b60e21b5f5260045ffd5b63bfa51ee360e01b5f5260045ffd5b635646ba3b60e11b5f5260045ffd5b630adc448560e21b5f5260045ffd5b630376a9ef60e31b5f5260045ffd5b6365c991a560e01b5f5260045ffd5b63adb838cd60e01b5f5260045ffd5b621e84809150115f611beb565b6328be116d60e21b5f5260045ffd5b63076eb25360e11b5f5260045ffd5b63cc15654960e01b5f5260045ffd5b632a7f863d60e21b5f5260045ffd5b6302f22cad60e61b5f5260045ffd5b6004356001600160401b038116810361011f57602435916001600160401b038316830361011f575f6001600160401b038060055494169416905b61ffff811684811015611dea57805f52600660205260405f20865f5260205260405f20835f52602052600160405f2001548414611de15750611ddc90611783565b611d9b565b94505050505090565b50505050505063ffffffff90565b8054905f815581611e07575050565b5f5260205f20908101905b818110611e1d575050565b5f8155600101611e12565b90600160401b81116103d757815491818155828210611e4657505050565b5f5260205f2091820191015b818110611e5d575050565b5f8155600101611e52565b906001600160401b038151166fffffffffffffffff00000000000000006020845493836001600160401b03198616178655015160401b16916fffffffffffffffffffffffffffffffff191617179055565b60405190611ec8602083611267565b5f80835282815b828110611edb57505050565b602090604051611eea8161124b565b5f81525f838201525f60408201525f60608201525f60808201525f60a08201525f60c0820152606060e08201526060610100820152606061012082015260606101408201525f6101608201525f6101808201525f6101a08201525f6101c082015260606101e082015260606102008201525f6102208201525f6102408201525f61026082015282828501015201611ecf565b60055461ffff80831694939116808510156120fb578061ffff8316116120f3575b508361ffff8216106120e75761ffff91611fb691611820565b16611fc081611296565b92611fce6040519485611267565b818452601f19611fdd83611296565b015f5b8181106120465750505f5b61ffff811690838210156120405781830161ffff81116103b05761203b9261ffff61203592165f52600460205261202460405f206114ff565b61202e828a61186d565b528761186d565b50611783565b611feb565b50505050565b6020906040516120558161124b565b5f81525f838201525f60408201525f60608201525f60808201525f60a08201525f60c0820152606060e08201526060610100820152606061012082015260606101408201525f6101608201525f6101808201525f6101a08201525f6101c082015260606101e082015260606102008201525f6102208201525f6102408201525f61026082015282828901015201611fe0565b50509050611af1611eb9565b90505f611f9d565b5050509050611af1611eb9565b8051905f908215801561216c575b612165575f915b83831061212d5750505050600190565b612137838361186d565b5190620f4240821161215c5781106121545760019092019161211d565b505050505f90565b50505050505f90565b5050505f90565b508051156118595760208101511515612116565b8051801515918261219057505090565b5f19820192509082116103b057620f4240916121ab9161186d565b511490565b8051905f90815b8383106121c75750505050600190565b6121d1838361186d565b51908110612154576001909201916121b7565b8051905f90620f423f5b8383106121fe5750505050600190565b612208838361186d565b51908111612154576001909201916121ee56fea26469706673582212201a0e5b061dbc5669db9937ab714356062c9af05eea7b1d4bb9eeaf0073ef81fe64736f6c634300081e0033"},"sourceId":"src/Registry.sol","sourcemap":"306:22119:16:-:0;;;;;;;;;;;;;-1:-1:-1;;306:22119:16;;;;-1:-1:-1;;;;;306:22119:16;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;306:22119:16;;;;;;;;699:6;;306:22119;-1:-1:-1;306:22119:16;;-1:-1:-1;;;;;;306:22119:16;;;;;;;;;;;;;;;;;-1:-1:-1;306:22119:16;;;;;;-1:-1:-1;306:22119:16;;;;;-1:-1:-1;306:22119:16","userdoc":{"errors":{"ChainAlreadyExists()":[{"notice":"Reverts if adding a chain to an asset that already exists."}],"IndexOutOfBounds()":[{"notice":"Reverts if the asset index is out of bounds."}],"InvalidBufferMultiple()":[{"notice":"Reverts if the buffer multiple value is less than 1% or greater than 2%."}],"InvalidCollateralFactor()":[{"notice":"Reverts if the collateral factor (CF) specified as part of risk parameters is greater than one"}],"InvalidInitialMarginsClamps()":[{"notice":"Reverts if the initial margin clamps specified as part of risk parameters are not increasing or are above 100"}],"InvalidInitialMarginsConfiguration()":[{"notice":"Reverts if the size of the initial margin clamps does not match the size of the initial margin factors (specified as part of risk parameters)"}],"InvalidInitialMarginsFactors()":[{"notice":"Reverts if the initial margin clamps specified as part of risk parameters are not decreasing or are above 100"}],"InvalidInterestKinks()":[{"notice":"Reverts if the interest kinks specified as part of risk parameters are not increasing from 0 to 1"}],"InvalidLiabilityFactor()":[{"notice":"Reverts if the liability factor (LF) specified as part of risk parameters is greater than one"}],"InvalidMaxFundingRate()":[{"notice":"Reverts if the funding rate cap specified as part of risk parameters is greater than ~1000% APR"}],"InvalidMaxUtilizationRate()":[{"notice":"Reverts if the utilization rate cap specified as part of risk parameters is greater than ~1000% APR"}],"InvalidRateInterestKinks()":[{"notice":"Reverts if the interest rates specified as part of risk parameters are not increasing"}],"InvalidUSDInterestKinks()":[{"notice":"Reverts if the USD-denominated interest kinks specified as part of risk parameters are not increasing from 0 to 1"}],"InvalidUSDRateInterestKinks()":[{"notice":"Reverts if the USD-denominated interest rates specified as part of risk parameters are not increasing"}],"InvalidUtilizationCap()":[{"notice":"Reverts if the utilization cap specified as part of risk parameters is greater than one"}],"NoPendingRiskParameters(uint16)":[{"notice":"Reverts if there is are no risk parameters queued for the specified asset"}],"NotAdmin()":[{"notice":"Reverts if caller is not the admin."}],"NotRiskManager()":[{"notice":"Reverts if caller is not the risk manager multisig."}],"RiskManagerNotSet()":[{"notice":"Reverts if the risk manager is not set."}],"TooSoon(uint16,uint256)":[{"notice":"Reverts if the pending risk parameters are not yet eligible for application"}],"ZeroAddress()":[{"notice":"Reverts if an address is zero."}]},"events":{"Max1HrDepositChanged((uint64,uint64),uint16,uint256,uint256)":{"notice":"Signals that the maximum hourly deposit has changed for a given asset"},"MaxDepositChanged((uint64,uint64),uint16,uint256,uint256)":{"notice":"Signals that the maximum deposit has changed for a given asset"},"MinWeightChanged((uint64,uint64),uint16,uint256,uint256)":{"notice":"Signals that the minimum weight has changed for a given asset"}},"kind":"user","methods":{"admin()":{"notice":"Address of the admin; primarily used for initial setup."},"applyPendingRiskParameters(uint16)":{"notice":"Applies the pending risk parameters for the specified asset if they exist."},"constructor":{"notice":"Contract constructor."},"feeAccount()":{"notice":"Account for receiving fees and paying rewards."},"getAssetData((uint64,uint64),uint16)":{"notice":"Retrieves asset data for a specific asset and chain."},"getAssetIndex((uint64,uint64),bytes32)":{"notice":"Returns the asset index for a given chain and address."},"getAssets(uint16,uint16)":{"notice":"Returns all registered asset data across all chains."},"getRiskParameters(uint16,uint16)":{"notice":"Returns the full list of risk parameters for all registered assets."},"pendingRiskParameters(uint16)":{"notice":"Mapping of asset index to new risk parameters to be applied to the registry, but only after they become eligible"},"riskManagerMultisig()":{"notice":"Multisig wallet address responsible for managing risk-related configurations."},"riskParameterChangeDelaySeconds()":{"notice":"Number of seconds to wait before new risk parameters become effective"},"riskParameters(uint16)":{"notice":"Mapping of asset index to associated risk parameters."},"setAdmin(address)":{"notice":"Updates the admin address."},"setAssetData((uint16,bytes32,(uint64,uint64),uint256,uint256,uint256))":{"notice":"Sets or updates asset data for a specific asset index and chain."},"setPendingRiskParameters(uint16,(uint8,uint8,uint256,uint256,uint256,uint256,bool,uint256[],uint256[],uint256[],uint256[],uint256,uint256,int256,uint256,uint256[],uint256[],uint256,uint256,uint256))":{"notice":"Sets pending risk parameters for a specific asset index."},"setRiskManagerMultisig(address)":{"notice":"Updates the risk manager multisig address."}},"notice":"Central registry for managing assets and associated risk parameters across multiple chains.","version":1}},"Settler":{"abi":[{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onAtomicSettlement","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}],"contractName":"Settler","deploymentBytecode":{"bytecode":"0x6080806040523460135760c0908160188239f35b5f80fdfe60808060405260043610156011575f80fd5b5f3560e01c633f1d584e146023575f80fd5b3460865760603660031901126086576004356001600160a01b0381160360865760443567ffffffffffffffff811160865736602382011215608657806004013567ffffffffffffffff81116086573691016024011160865780620f424060209252f35b5f80fdfea2646970667358221220a8714c703f33fadc15c70b5e85fe4339baf5c2eadde619da4d23e7a4d23416e264736f6c634300081e0033"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"onAtomicSettlement(address,uint256,bytes)":"0x3f1d584e"},"runtimeBytecode":{"bytecode":"0x60808060405260043610156011575f80fd5b5f3560e01c633f1d584e146023575f80fd5b3460865760603660031901126086576004356001600160a01b0381160360865760443567ffffffffffffffff811160865736602382011215608657806004013567ffffffffffffffff81116086573691016024011160865780620f424060209252f35b5f80fdfea2646970667358221220a8714c703f33fadc15c70b5e85fe4339baf5c2eadde619da4d23e7a4d23416e264736f6c634300081e0033"},"sourceId":"src/Settler.sol","sourcemap":"59:173:0:-:0;;;;;;;;;;;;;;;;;","userdoc":{"kind":"user","methods":{},"version":1}},"SigTest":{"abi":[{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"check","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"contractName":"SigTest","deploymentBytecode":{"bytecode":"0x608080604052346015576101c9908161001a8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c63197ff59b14610024575f80fd5b346100a35760603660031901126100a3576004356001600160a01b03811681036100a35760443567ffffffffffffffff81116100a357366023820112156100a357806004013567ffffffffffffffff81116100a35736602482840101116100a3576020926024610099930190602435906100a7565b6040519015158152f35b5f80fd5b92939290915f906001600160a01b0383161561018a576040519160048301602484019560448501916064860193873b156101115750936064938a80948a9b9c9460209b9a9998630b135d3f60e11b8a525260408a52523701915afa9051630b135d3f60e11b141690565b99935050939550508060401461015e5760411461012e5750505050565b60408092939496508101355f1a60205281375b5f526020600160805f825afa511860601b3d11915f606052604052565b5060208082013560ff81901c601b0190915290356040526001600160ff1b031660605291935090610141565b505f945050505056fea26469706673582212208a106949f349498c2239c8e95c70bad1b3b3e62a5294423000b592793b14c09564736f6c634300081c0033"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"check(address,bytes32,bytes)":"0x197ff59b"},"runtimeBytecode":{"bytecode":"0x60806040526004361015610011575f80fd5b5f3560e01c63197ff59b14610024575f80fd5b346100a35760603660031901126100a3576004356001600160a01b03811681036100a35760443567ffffffffffffffff81116100a357366023820112156100a357806004013567ffffffffffffffff81116100a35736602482840101116100a3576020926024610099930190602435906100a7565b6040519015158152f35b5f80fd5b92939290915f906001600160a01b0383161561018a576040519160048301602484019560448501916064860193873b156101115750936064938a80948a9b9c9460209b9a9998630b135d3f60e11b8a525260408a52523701915afa9051630b135d3f60e11b141690565b99935050939550508060401461015e5760411461012e5750505050565b60408092939496508101355f1a60205281375b5f526020600160805f825afa511860601b3d11915f606052604052565b5060208082013560ff81901c601b0190915290356040526001600160ff1b031660605291935090610141565b505f945050505056fea26469706673582212208a106949f349498c2239c8e95c70bad1b3b3e62a5294423000b592793b14c09564736f6c634300081c0033"},"sourceId":"src/SigTest.sol","sourcemap":"140:221:1:-:0;;;;;;;;;;;;;;;;;","userdoc":{"kind":"user","methods":{},"version":1}},"SignatureTest":{"abi":[{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct SignatureTest.Settlement","name":"order","type":"tuple"},{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"uint64","name":"account","type":"uint64"},{"internalType":"uint256","name":"validUntil","type":"uint256"}],"name":"getSettlementPayload","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"digest","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"getSigningAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct SignatureTest.Withdrawal","name":"withdrawal","type":"tuple"},{"internalType":"bytes32","name":"user","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"bytes32","name":"epochHash","type":"bytes32"}],"name":"getWithdrawalPayload","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_domainSeparator","type":"bytes32"}],"name":"setDomainSeparator","outputs":[],"stateMutability":"nonpayable","type":"function"}],"contractName":"SignatureTest","deploymentBytecode":{"bytecode":"0x608080604052346015576103e4908161001a8239f35b5f80fdfe6080806040526004361015610012575f80fd5b5f3560e01c908163035563461461025e5750806336116c161461018b5780637438b937146101735780639e5c3980146100735763f698da2514610053575f80fd5b3461006f575f36600319011261006f5760205f54604051908152f35b5f80fd5b3461006f573660031901610100811261006f5760a01361006f5760c43567ffffffffffffffff811680910361006f575f546bffffffffffffffffffffffff196100ba610362565b60601b16916044356001600160a01b038116810361006f5761016f93604051937fd5bba88286cccde9162e20a797ff293aac0b11190037e71286b8a5271985e4cb60208601526040850152606084015260243560808401526bffffffffffffffffffffffff199060601b1660a083015260643560c083015260a43560e083015261010082015260843561012082015260e435610140820152610140815261016361016082610378565b60405191829182610338565b0390f35b3461006f57602036600319011261006f576004355f55005b3461006f57366003190160e0811261006f5760601361006f576084356001600160a01b038116810361006f575f5461016f916bffffffffffffffffffffffff196101d3610362565b60601b16604051927f797aea45f9ae7a23c83a831da6478b151bf9c36a60c32d897309fb02a25102ba602085015260408401526060830152602435608083015260643560a083015260443560c083015260a43560e083015260c4356101008301526bffffffffffffffffffffffff199060601b16610120820152610120815261016361014082610378565b3461006f57604036600319011261006f576004356024359167ffffffffffffffff831161006f573660238401121561006f5782600401359167ffffffffffffffff831161006f5760248401366024858701011161006f576020945f9480604014610310576041146102e057505050505b6040516001600160a01b039091168152f35b604092939450606401355f1a855281375b5f5281604060805f60015afa505f6060523d60601851906040526102ce565b506044013560ff81901c601b01865290356040526001600160ff1b03166060529091506102f1565b602060409281835280519182918282860152018484015e5f828201840152601f01601f1916010190565b6004356001600160a01b038116810361006f5790565b90601f8019910116810190811067ffffffffffffffff82111761039a57604052565b634e487b7160e01b5f52604160045260245ffdfea2646970667358221220a2f355b36c760bb58250919fd43010925bdca95acc99830f86f5bc7e95898c4064736f6c634300081e0033"},"devdoc":{"kind":"dev","methods":{},"version":1},"methodIdentifiers":{"domainSeparator()":"0xf698da25","getSettlementPayload((address,uint256,address,uint256,uint256),bytes32,uint64,uint256)":"0x9e5c3980","getSigningAddress(bytes32,bytes)":"0x03556346","getWithdrawalPayload((address,uint256,uint256),bytes32,address,uint256,bytes32)":"0x36116c16","setDomainSeparator(bytes32)":"0x7438b937"},"runtimeBytecode":{"bytecode":"0x6080806040526004361015610012575f80fd5b5f3560e01c908163035563461461025e5750806336116c161461018b5780637438b937146101735780639e5c3980146100735763f698da2514610053575f80fd5b3461006f575f36600319011261006f5760205f54604051908152f35b5f80fd5b3461006f573660031901610100811261006f5760a01361006f5760c43567ffffffffffffffff811680910361006f575f546bffffffffffffffffffffffff196100ba610362565b60601b16916044356001600160a01b038116810361006f5761016f93604051937fd5bba88286cccde9162e20a797ff293aac0b11190037e71286b8a5271985e4cb60208601526040850152606084015260243560808401526bffffffffffffffffffffffff199060601b1660a083015260643560c083015260a43560e083015261010082015260843561012082015260e435610140820152610140815261016361016082610378565b60405191829182610338565b0390f35b3461006f57602036600319011261006f576004355f55005b3461006f57366003190160e0811261006f5760601361006f576084356001600160a01b038116810361006f575f5461016f916bffffffffffffffffffffffff196101d3610362565b60601b16604051927f797aea45f9ae7a23c83a831da6478b151bf9c36a60c32d897309fb02a25102ba602085015260408401526060830152602435608083015260643560a083015260443560c083015260a43560e083015260c4356101008301526bffffffffffffffffffffffff199060601b16610120820152610120815261016361014082610378565b3461006f57604036600319011261006f576004356024359167ffffffffffffffff831161006f573660238401121561006f5782600401359167ffffffffffffffff831161006f5760248401366024858701011161006f576020945f9480604014610310576041146102e057505050505b6040516001600160a01b039091168152f35b604092939450606401355f1a855281375b5f5281604060805f60015afa505f6060523d60601851906040526102ce565b506044013560ff81901c601b01865290356040526001600160ff1b03166060529091506102f1565b602060409281835280519182918282860152018484015e5f828201840152601f01601f1916010190565b6004356001600160a01b038116810361006f5790565b90601f8019910116810190811067ffffffffffffffff82111761039a57604052565b634e487b7160e01b5f52604160045260245ffdfea2646970667358221220a2f355b36c760bb58250919fd43010925bdca95acc99830f86f5bc7e95898c4064736f6c634300081e0033"},"sourceId":"src/SignatureTest.sol","sourcemap":"112:2016:17:-:0;;;;;;;;;;;;;;;;;","userdoc":{"kind":"user","methods":{},"version":1}}},"manifest":"ethpm/3","sources":{"src/Checkpointer.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {EfficientHashLib} from \"solady/utils/EfficientHashLib.sol\";\nimport {SignatureCheckerLib} from \"solady/utils/SignatureCheckerLib.sol\";\n\n/**\n * @title Checkpointer\n * @notice Tracks and validates state root checkpoints using EIP-712 signatures from admin and leader nodes.\n * @dev Designed for use in DStack-like distributed settlement systems.\n */\ncontract Checkpointer {\n /**\n * @notice Address with the authority to set initial parameters.\n * @dev Should be set to the DStack app shared secret public key.\n */\n address public admin;\n\n /**\n * @notice Public key of the current designated leader node.\n * @dev Leader is responsible for signing and submitting new checkpoints.\n */\n address public leader;\n\n /**\n * @notice Gnosis Safe address used as the council multisig.\n * @dev Can rotate the leader and self.\n */\n address public councilMultisig;\n\n /**\n * @notice Monotonically increasing nonce for checkpoint submissions.\n * @dev Used to prevent replay attacks and enforce checkpoint ordering.\n */\n uint256 public stateRootNonce;\n\n /// @notice Typehash used for EIP-712 encoding of the Checkpoint struct.\n bytes32 public constant CHECKPOINT_TYPEHASH =\n keccak256(\"Checkpoint(uint256 nonce,uint8[] stateRoot,string[] approvedWithdrawals)\");\n\n /**\n * @notice Emitted when a new list of approved withdrawals is recorded in a checkpoint.\n * @param approvedWithdrawals List of withdrawal IDs approved in the checkpoint.\n */\n event Withdrawals(string[] approvedWithdrawals);\n\n /// @notice Cached domain separator for EIP-712 signature verification.\n bytes32 internal _domainSeparator;\n\n /**\n * @notice The current state root, encoded as a serialized vector.\n * @dev Serialized as `(user, eth_balance, usdc_balance, deposit_nonce, is_mm)` tuples.\n * In production, this may store multiple roots and rotate.\n */\n uint8[] public stateRoot;\n\n /// @notice Reverts if caller is not the admin.\n error NotAdmin();\n\n /// @notice Reverts if a value has already been set.\n error AlreadySet();\n\n /// @notice Reverts if caller is not the current council multisig.\n error NotCouncilMultisig();\n\n /// @notice Reverts if a signature does not match the expected signer or payload.\n error InvalidSignature();\n\n /**\n * @notice Contract constructor.\n * @dev Sets the deployer as the initial admin.\n */\n constructor() {\n admin = msg.sender;\n }\n\n /**\n * @notice Sets the EIP-712 domain separator used for verifying signatures.\n * @param domainSeparator The domain separator to store.\n */\n function setDomainSeparator(bytes32 domainSeparator) external {\n if (msg.sender != admin) revert NotAdmin();\n if (_domainSeparator != 0) revert AlreadySet();\n _domainSeparator = domainSeparator;\n }\n\n /**\n * @notice Transfers admin control to a new address.\n * @param newAdmin The new admin address.\n */\n function setAdmin(address newAdmin) external {\n if (msg.sender != admin) revert NotAdmin();\n require(newAdmin != address(0));\n admin = newAdmin;\n }\n\n /**\n * @notice Sets the initial council multisig address.\n * @param newCouncilMultisig The council's Gnosis Safe address.\n */\n function setInitialCouncilMultisig(address newCouncilMultisig) external {\n if (msg.sender != admin) revert NotAdmin();\n if (councilMultisig != address(0)) revert AlreadySet();\n councilMultisig = newCouncilMultisig;\n }\n\n /**\n * @notice Allows the current council to rotate itself to a new address.\n * @param newCouncilMultisig The new multisig address.\n */\n function setNewCouncilMultisig(address newCouncilMultisig) external {\n if (msg.sender != councilMultisig) revert NotCouncilMultisig();\n councilMultisig = newCouncilMultisig;\n }\n\n /**\n * @notice Sets the leader node address.\n * @dev This should be reviewed depending on the leader rotation mechanism.\n * @param newLeader The address of the new leader node.\n */\n function setLeader(address newLeader) external {\n if (msg.sender != councilMultisig) revert NotCouncilMultisig();\n leader = newLeader;\n }\n\n /**\n * @notice Checkpoint submitted by a node to update the system state.\n * @dev Requires valid EIP-712 signatures from both admin and leader.\n * @param sharedSignature Signature by the admin.\n * @param leaderSignature Signature by the leader.\n * @param _checkpoint The checkpoint payload to commit.\n */\n function checkpoint(\n bytes calldata sharedSignature,\n bytes calldata leaderSignature,\n Checkpoint calldata _checkpoint\n ) external {\n require(_checkpoint.nonce == stateRootNonce); // dev: Nonce mismatch\n\n // Compute the EIP-712 struct hash.\n bytes32 structHash = EfficientHashLib.hash(\n abi.encode(\n CHECKPOINT_TYPEHASH,\n _checkpoint.nonce,\n EfficientHashLib.hash(abi.encodePacked(_checkpoint.stateRoot)),\n hashStringArray(_checkpoint.approvedWithdrawals)\n )\n );\n\n // Check both admin and leader signatures.\n bytes32 digest =\n EfficientHashLib.hash(abi.encodePacked(\"\\x19\\x01\", _domainSeparator, structHash));\n\n if (!SignatureCheckerLib.isValidSignatureNow(admin, digest, sharedSignature)) {\n revert InvalidSignature();\n }\n\n if (!SignatureCheckerLib.isValidSignatureNow(leader, digest, leaderSignature)) {\n revert InvalidSignature();\n }\n\n stateRootNonce++;\n stateRoot = _checkpoint.stateRoot;\n\n emit Withdrawals(_checkpoint.approvedWithdrawals);\n }\n\n /**\n * @notice Internal helper for hashing an array of strings.\n * @dev Each string is hashed individually and packed before final hashing.\n * @param arr The array of strings to hash.\n * @return A single keccak256 hash of the packed array of hashed strings.\n */\n function hashStringArray(string[] memory arr) internal pure returns (bytes32) {\n bytes32[] memory hashedStrings = new bytes32[](arr.length);\n for (uint256 i = 0; i < arr.length; i++) {\n hashedStrings[i] = EfficientHashLib.hash(bytes(arr[i]));\n }\n return EfficientHashLib.hash(abi.encodePacked(hashedStrings));\n }\n\n /**\n * @notice Struct defining a checkpoint message.\n * @dev Checkpoints include the current state root, a nonce, and a list of approved withdrawals.\n */\n struct Checkpoint {\n uint256 nonce;\n uint8[] stateRoot;\n string[] approvedWithdrawals;\n }\n}\n","urls":[]},"src/CredentialManager.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {SignatureCheckerLib} from \"solady/utils/SignatureCheckerLib.sol\";\nimport {EfficientHashLib} from \"solady/utils/EfficientHashLib.sol\";\nimport {IAdminUpdateStrategy} from \"./interfaces/IAdminUpdateStrategy.sol\";\nimport {IAutomataDcapAttestation} from \"./interfaces/IAutomataDcapAttestation.sol\";\n\n/// @title CredentialManager\n/// @notice The centralized Root of Trust for the TEE Clearing Engine.\n/// @dev This contract acts as the governance layer and the vault registry. It manages the\n/// set of authorized operators, enforces quorum consensus for critical updates, and\n/// maintains the registry of deposit vaults across different chains.\n/// It combines immediate multi-sig actions for operational tasks with timelocked\n/// actions for high-risk configuration changes.\ncontract CredentialManager {\n using SignatureCheckerLib for address;\n\n // =============================================================\n // STRUCTS\n // =============================================================\n\n /// @notice Configuration for a specific chain/vault.\n struct ChainConfig {\n uint64 blockTimeMs;\n // Confs\n uint8 defaultConfirmations;\n uint8 depositIngestConfirmations;\n uint8 withdrawalIngestConfirmations;\n uint8 settlementIngestConfirmations;\n }\n\n /// @notice Represents a deposit vault deployed on a specific chain.\n /// @dev Addresses are stored as bytes32 to support non-EVM chains (e.g., Solana, SVM).\n struct Vault {\n uint8 routingId;\n uint256 vmId; // ChainId for EVM chains.\n /// @notice The address of the vault on that chain (left-aligned or native format).\n bytes32 vaultAddress;\n ChainConfig config;\n }\n\n /// @notice Tracks the lifecycle state of a timelocked operation.\n struct TimelockOp {\n /// @notice The timestamp (seconds since unix epoch) after which the operation can be executed.\n uint64 eta;\n /// @notice True if the operation has already been executed.\n bool executed;\n /// @notice True if the operation was explicitly canceled by the operators.\n bool canceled;\n /// @notice The type hash of the operation (e.g., OP_SET_RISK_MANAGER) for verification.\n bytes32 opType;\n }\n\n /// @notice Defines the expected state of the TEE software.\n struct MeasurementProfile {\n bool active; // Is this profile currently allowed?\n bytes32 mrtd; // Mandatory (Code Identity)\n bytes32 rtmr0; // Optional (Set to 0 to skip check)\n bytes32 rtmr1; // Optional\n bytes32 rtmr2; // Optional\n bytes32 rtmr3; // Optional\n }\n\n struct RestartCandidate {\n address leader;\n uint256 epoch;\n bytes32 checkpointHash;\n bool exists;\n }\n\n // =============================================================\n // ERRORS\n // =============================================================\n\n /// @notice Thrown when a signature belongs to an address that is not a registered operator.\n /// @param signer The address recovered from the signature.\n error NotOperator(address signer);\n\n /// @notice Thrown when the provided signatures are not sorted by signer address or contain duplicates.\n /// @dev Signatures must be sorted strictly ascending (A < B) to prevent duplicate counting in O(N).\n error SignersNotSortedOrUnique();\n\n /// @notice Thrown when the number of valid signatures provided is less than the required threshold.\n /// @param provided The number of signatures provided.\n /// @param required The current `quorumThreshold` required.\n error InsufficientSignatures(uint256 provided, uint256 required);\n\n /// @notice Thrown when attempting to set a quorum threshold that is 0 or greater than the total operators.\n /// @param newQuorum The proposed threshold.\n /// @param operatorCount The total number of registered operators.\n error InvalidQuorum(uint256 newQuorum, uint256 operatorCount);\n\n /// @notice Thrown when attempting to execute a timelock before the delay has elapsed.\n /// @param opId The unique hash of the operation.\n /// @param readyAt The timestamp when the operation becomes executable.\n /// @param nowTs The current block timestamp.\n error TimelockNotReady(bytes32 opId, uint256 readyAt, uint256 nowTs);\n\n /// @notice Thrown when attempting to act on a timelock ID that does not exist or was never scheduled.\n /// @param opId The operation hash.\n error TimelockUnknown(bytes32 opId);\n\n /// @notice Thrown when attempting to execute or schedule an operation that has already been executed.\n /// @param opId The operation hash.\n error TimelockAlreadyExecuted(bytes32 opId);\n\n /// @notice Thrown when attempting to execute or cancel an operation that has already been canceled.\n /// @param opId The operation hash.\n error TimelockAlreadyCanceled(bytes32 opId);\n\n /// @notice Thrown when a timelock delay is set to 0 (invalid safety margin).\n /// @param delay The provided delay in seconds.\n error InvalidDelay(uint256 delay);\n\n /// @notice Thrown when attempting to cancel an operation that cannot be canceled (e.g., already executed).\n error CannotCancel();\n\n /// @notice Thrown when a critical configuration address (e.g., Risk Manager) is set to address(0).\n error ZeroAddress();\n\n /// @notice Thrown when a Vault address is empty (bytes32(0)).\n error InvalidVaultAddr();\n\n /// @notice Thrown when attempting to register a strategy for a chain that already has one.\n error StrategyAlreadyExists();\n\n /// @notice Thrown when attempting to update vault admins on a chain that has no registered strategy.\n error NoStrategy();\n\n /// @notice Thrown when a requested vault cannot be found for the specified chain.\n /// @param routingId The routing ID of the vault.\n /// @param vmId The Chain ID for EVM chains requested.\n error VaultNotFound(uint256 routingId, uint256 vmId);\n\n /// @notice Thrown when the measured TEE state does not match the expected state.\n error MeasurementMismatch(bytes32 expected, bytes32 actual, string field);\n\n /// @notice Thrown when the ZK Proof attesting measurements is invalid.\n error InvalidZkProof();\n\n /// @notice Thrown when the supplied epoch is invalid\n error InvalidEpoch(uint256 expected, uint256 actual);\n /// @notice Thrown when a Quote ReportData does not match params.\n error InvalidReportData();\n /// @notice Thrown when a Quote length is invalid.\n error InvalidQuoteLength();\n /// @notice Thrown when a Quote verifier is invalid.\n error InvalidVerifier();\n /// @notice Thrown when the used profile is not active.\n error ProfileInactive(uint256 profileId);\n /// @notice Thrown when the used profile does not exist.\n error InvalidProfileId();\n /// @notice Thrown when the used profile is configured incorrectly.\n error InvalidProfileConfig();\n\n // Certificate gathering errors\n error GatheringActive();\n error GatheringNotActive();\n error GatheringNotExpired();\n error AmbiguousState();\n error NoCandidate();\n error ProposedEpochTooLow(uint256 current, uint256 proposed);\n\n // =============================================================\n // CONSTANTS & TYPEHASHES\n // =============================================================\n\n /// @dev EIP-712 Domain Separator typehash.\n bytes32 private constant _EIP712_DOMAIN_TYPEHASH = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n\n /// @dev EIP-712 name hash for this contract.\n bytes32 private constant _NAME_HASH = keccak256(\"CredentialManager\");\n\n /// @dev EIP-712 version hash.\n bytes32 private constant _VERSION_HASH = keccak256(\"1\");\n\n /// @dev Generic Action typehash used for all governance signatures.\n /// Structure: Action(bytes32 opType, bytes32 paramsHash, uint256 nonce)\n bytes32 private constant _ACTION_TYPEHASH =\n keccak256(\"Action(bytes32 opType,bytes32 paramsHash,uint256 nonce)\");\n\n /// @dev Used for appointing a leader in the absence of a leader - for bootstrap or emergency recovery.\n bytes32 public constant OP_APPOINT_LEADER = keccak256(\"OP_APPOINT_LEADER\");\n\n // --- Operation Types (for Signature Verification) ---\n\n // Immediate Actions (Executed immediately upon valid quorum)\n bytes32 public constant OP_SET_QUORUM = keccak256(\"OP_SET_QUORUM\");\n bytes32 public constant OP_ADD_VAULT = keccak256(\"OP_ADD_VAULT\");\n bytes32 public constant OP_REGISTER_STRATEGY = keccak256(\"OP_REGISTER_ADMIN_UPDATE_STRATEGY\");\n bytes32 public constant OP_SET_VAULT_ADMINS = keccak256(\"OP_SET_DEPOSIT_VAULT_ADMINS\");\n bytes32 public constant OP_CANCEL_TIMELOCK = keccak256(\"OP_CANCEL_TIMELOCK\");\n bytes32 public constant OP_WITHDRAW = keccak256(\"OP_WITHDRAW\");\n\n // Timelocked Actions (Scheduled first, executed later)\n bytes32 public constant OP_SET_RISK_MANAGER = keccak256(\"OP_SET_RISK_MANAGER\");\n bytes32 public constant OP_SET_REGISTRY = keccak256(\"OP_SET_REGISTRY\");\n bytes32 public constant OP_SET_MEASUREMENTS = keccak256(\"OP_SET_MEASUREMENTS\");\n bytes32 public constant OP_SET_DELAY = keccak256(\"OP_SET_DELAY\");\n bytes32 public constant OP_MANAGE_PROFILE = keccak256(\"OP_MANAGE_PROFILE\");\n\n // Restarts\n bytes32 public constant OP_RESTART = keccak256(\"OP_RESTART\");\n bytes32 public constant OP_SET_AUTOMATA_VERIFIER = keccak256(\"OP_SET_AUTOMATA_VERIFIER\");\n\n // Certificate gathering\n uint256 public constant GATHERING_DURATION = 1 hours;\n\n // =============================================================\n // STORAGE\n // =============================================================\n\n // --- Governance State ---\n\n /// @notice TEMP Admin path, to be revised later.\n address public admin;\n\n /// @notice The list of authorized Clearing Engine operator addresses (EOAs).\n /// @dev These keys form the root of trust for the system.\n address[] public operators;\n\n /// @notice Lookup to check if an address is an operator.\n mapping(address => bool) public isOperator;\n\n /// @notice The minimum number of signatures required to execute a governance action.\n uint256 public quorumThreshold;\n\n /// @notice A monotonically increasing nonce for governance actions.\n /// @dev Included in every signed hash to strictly order operations and prevent replay attacks.\n uint256 public governanceNonce;\n\n /// @notice Maps Operator (EOA) -> Attested Key (TEE Address).\n /// @dev Used to verify that a TEE signature belongs to a specific operator.\n mapping(address => bytes32) public operatorToAttestedKey;\n\n /// @notice The current active leader (Operator Address).\n /// @dev The leader is responsible for coordinating the clearing engine.\n address public leader;\n\n // --- Execution State (Vault Registry) ---\n\n /// @notice The registry of all authorized Deposit Vaults.\n /// @dev This list is strictly append-only; vaults cannot be removed to prevent history modification.\n Vault[] public vaults;\n\n /// @notice Maps a RoutingID to the VMID to the Strategy Contract responsible for sending messages to it.\n /// @dev Used to abstract cross-chain messaging logic (e.g., LayerZero, Optimism Messenger).\n mapping(uint256 => mapping(uint256 => IAdminUpdateStrategy)) public adminUpdateStrategies;\n\n // --- Configuration ---\n\n /// @notice The address of the Risk Manager (or multisig) authorized to adjust risk parameters.\n address public riskManager;\n\n /// @notice The address of the global Registry Contract used for asset/settler configurations.\n address public registryContract;\n\n // --- Timelock State ---\n\n /// @notice Configuration mapping for how long specific operations must be delayed.\n /// @dev e.g., OP_SET_REGISTRY -> 72 hours.\n mapping(bytes32 => uint256) public timelockDelayFor;\n\n /// @notice Stores the status of individual scheduled operations by their hash ID.\n mapping(bytes32 => TimelockOp) public timelockOps;\n\n // --- TDX measurements ---\n\n /// @notice The current \"Gold Image\" measurements required for valid Quotes. Matches based on profile.\n mapping(uint256 => MeasurementProfile) public measurementProfiles;\n uint256 public nextProfileId = 1;\n\n // --- Restarts ---\n\n /// @notice Tracks the logical era of the TEE state to prevent replay attacks.\n /// @dev Incremented on every successful restart.\n uint256 public epoch;\n\n /// @notice The hash of the system state (inventory) associated with the current epoch.\n /// @dev New nodes verify this hash against the leader's data to ensure they are on the correct fork.\n bytes32 public latestCheckpointHash;\n\n // ZK Verifier Contract (Automata)\n IAutomataDcapAttestation public automataVerifier;\n\n // --- Certificate gathering ---\n uint256 public restartGatheringDeadline; // 0 = Inactive, >0 = Active\n RestartCandidate public bestCandidate;\n bool public isRestartAmbiguous;\n\n // =============================================================\n // EVENTS\n // =============================================================\n\n /// @notice Emitted when a new operator is added during initialization.\n event OperatorAdded(address indexed operator);\n\n /// @notice Emitted when the signature threshold is updated.\n event QuorumThresholdUpdated(uint256 oldThreshold, uint256 newThreshold);\n\n /// @notice Emitted when a new vault is added to the registry.\n event VaultAdded(\n uint256 indexed routingId, uint256 indexed vmId, bytes32 vaultAddr, ChainConfig config\n );\n\n /// @notice Emitted when a new cross-chain strategy is registered.\n event DepositVaultAdministratorsUpdated(\n uint256 indexed routingId,\n uint256 indexed vmId,\n address[] newAdministrators,\n uint256 newWithdrawalQuorum\n );\n\n /// @notice Emitted when the admin set of a remote vault is updated.\n event DepositVaultAdministratorsUpdated(\n uint256 indexed chainId, address[] newAdministrators, uint256 newWithdrawalQuorum\n );\n\n /// @notice Emitted when a new cross-chain strategy is registered.\n event AdminUpdateStrategyRegistered(\n uint256 indexed routingId, uint256 indexed vmId, address strategy\n );\n\n /// @notice Emitted when a new attested key for an operator is registered.\n event AttestedKeyRegistered(address indexed operator, bytes32 indexed newAttestedKey);\n\n /// @notice Emitted when the quorum leader is updated.\n event LeaderUpdated(address indexed newLeader, bytes32 indexed newAttestedKey);\n\n // Timelock Events\n event OperationScheduled(bytes32 indexed opId, bytes32 indexed opType, uint256 eta);\n event OperationExecuted(bytes32 indexed opId, bytes32 indexed opType);\n event OperationCanceled(bytes32 indexed opId, bytes32 indexed opType);\n\n event RiskManagerUpdated(address indexed oldRiskManager, address indexed newRiskManager);\n event RegistryUpdated(address indexed oldRegistry, address indexed newRegistry);\n event TimelockDelayUpdated(bytes32 indexed targetOpType, uint256 oldDelay, uint256 newDelay);\n\n // Measurement & Restart Events\n /// @notice Emitted when the measurements are updated.\n event MeasurementsUpdated(bytes32 newMrtd, bytes32 newRtmr0);\n event MeasurementProfileUpdated(uint256 indexed profileId, bool active);\n event EpochIncremented(uint256 newEpoch, bytes32 newCheckpointHash);\n event RestartExecuted(address indexed newLeader, uint256 indexed epoch);\n event AutomataVerifierUpdated(address indexed oldVerifier, address indexed newVerifier);\n\n // Certificate gathering events\n event RestartGatheringStarted(uint256 deadline);\n event RestartCandidateSubmitted(address indexed leader, uint256 epoch, bytes32 checkpointHash);\n event RestartAmbiguityDetected(uint256 epoch, bytes32 hash1, bytes32 hash2);\n\n // =============================================================\n // INITIALIZATION\n // =============================================================\n\n /// @notice Initializes the Credential Manager with the initial operator set and configuration.\n /// @param initialOperators The list of addresses that will form the initial governance council.\n /// @param initialQuorumThreshold The number of signatures required for valid governance actions.\n /// @param initialRiskManager The initial Risk Manager address.\n /// @param initialRegistryContract The initial Registry Contract address.\n constructor(\n address[] memory initialOperators,\n uint256 initialQuorumThreshold,\n address initialRiskManager,\n address initialRegistryContract,\n MeasurementProfile[] memory initialMeasurements,\n address initialAutomataVerifier\n ) {\n admin = msg.sender;\n\n if (initialRiskManager == address(0)) revert ZeroAddress();\n if (initialRegistryContract == address(0)) revert ZeroAddress();\n automataVerifier = IAutomataDcapAttestation(initialAutomataVerifier);\n\n _initOperators(initialOperators, initialQuorumThreshold);\n\n riskManager = initialRiskManager;\n registryContract = initialRegistryContract;\n // Start IDs at 1 so 0 can be used as a null/sentinel value\n nextProfileId = 1;\n\n for (uint256 i = 0; i < initialMeasurements.length; i++) {\n MeasurementProfile memory p = initialMeasurements[i];\n\n // Safety Check: Active profiles must have an MRTD\n if (p.active && p.mrtd == bytes32(0)) revert InvalidProfileConfig();\n\n measurementProfiles[nextProfileId] = p;\n emit MeasurementProfileUpdated(nextProfileId, p.active);\n nextProfileId++;\n }\n\n // Default Timelocks\n timelockDelayFor[OP_SET_RISK_MANAGER] = 48 hours;\n timelockDelayFor[OP_SET_REGISTRY] = 72 hours;\n timelockDelayFor[OP_MANAGE_PROFILE] = 7 days;\n timelockDelayFor[OP_SET_DELAY] = 7 days;\n }\n\n /// @dev Internal helper to process the operator list and set the threshold.\n function _initOperators(address[] memory initialOperators, uint256 initialQuorumThreshold)\n internal\n {\n uint256 n = initialOperators.length;\n if (n == 0) revert InvalidQuorum(initialQuorumThreshold, 0);\n if (initialQuorumThreshold == 0 || initialQuorumThreshold > n) {\n revert InvalidQuorum(initialQuorumThreshold, n);\n }\n\n for (uint256 i = 0; i < n; i++) {\n address op = initialOperators[i];\n if (op == address(0)) revert ZeroAddress();\n if (isOperator[op]) revert SignersNotSortedOrUnique();\n isOperator[op] = true;\n operators.push(op);\n emit OperatorAdded(op);\n }\n quorumThreshold = initialQuorumThreshold;\n emit QuorumThresholdUpdated(0, initialQuorumThreshold);\n }\n\n // =============================================================\n // QUORUM & KEYS\n // =============================================================\n\n /// @notice Allows an operator to register their TEE's attested key.\n /// @dev Maps the attested_pubkey of a new CE joining the quorum.\n /// @param newAttestedKey The address derived from the TEE's public key.\n function registerAttestedKey(bytes32 newAttestedKey) external {\n if (!isOperator[msg.sender]) revert NotOperator(msg.sender);\n if (newAttestedKey == bytes32(0)) revert ZeroAddress();\n\n operatorToAttestedKey[msg.sender] = newAttestedKey;\n emit AttestedKeyRegistered(msg.sender, newAttestedKey);\n }\n\n /// @notice Returns the full Council configuration.\n /// @dev Let's operators query for 'k, n' thresholds and the current council member list\".\n function getCouncilConfig()\n external\n view\n returns (address[] memory members, uint256 k, uint256 n)\n {\n return (operators, quorumThreshold, operators.length);\n }\n\n /// @notice Returns the current Leader's Operator Address and Attested Key.\n /// @dev When querying current leader, then the contract returns the active operator_pubkey and attested_pubkey.\n function getLeader() external view returns (address operator, bytes32 attestedKey) {\n return (leader, operatorToAttestedKey[leader]);\n }\n\n /// @dev Internal helper to update mappings.\n function _setAttestedKey(address op, bytes32 attKey) internal {\n operatorToAttestedKey[op] = attKey;\n emit AttestedKeyRegistered(op, attKey);\n }\n\n /// @dev Internal helper to rotate the leader for use in restarts.\n function _updateLeader(address newLeader) internal {\n if (!isOperator[newLeader]) revert NotOperator(newLeader);\n // Check bytes32 zero\n if (operatorToAttestedKey[newLeader] == bytes32(0)) revert ZeroAddress();\n leader = newLeader;\n\n emit LeaderUpdated(newLeader, operatorToAttestedKey[newLeader]);\n }\n\n /// @notice Manually appoints a leader. Used for bootstrapping or emergency recovery.\n function appointLeader(\n address newLeader,\n address[] calldata signers,\n bytes[] calldata signatures\n ) external {\n if (!isOperator[newLeader]) revert NotOperator(newLeader);\n\n // Leader MUST have a registered key, or they cannot sign Attestations/Checkpoints\n if (operatorToAttestedKey[newLeader] == bytes32(0)) revert ZeroAddress();\n\n bytes32 paramsHash = keccak256(abi.encode(newLeader));\n _requireQuorum(OP_APPOINT_LEADER, paramsHash, signers, signatures);\n\n _updateLeader(newLeader);\n }\n\n // =============================================================\n // RESTART CERTIFICATION & CERTIFICATE GATHERING\n // =============================================================\n\n /// @notice Step 1: Initiates the gathering window if the system is down.\n function initiateRestart() external {\n if (restartGatheringDeadline > block.timestamp) revert GatheringActive();\n\n // Start 1 hour window\n restartGatheringDeadline = block.timestamp + GATHERING_DURATION;\n\n // Clear previous state\n delete bestCandidate;\n isRestartAmbiguous = false;\n\n emit RestartGatheringStarted(restartGatheringDeadline);\n }\n\n /// @notice Restarts the system using a Trustless ZK Proof (Automata / SP1). The contract stores the \"Best\" candidate.\n /// @dev We compare Epochs. The highest epoch wins.\n /// @param tdxReportBody The 'Public Output' of the ZK Circuit (The TEE Quote Body).\n /// @param zkProof The Groth16 proof bytes.\n /// @param newLeader The address claiming leadership.\n /// @param checkpointHash The state hash being served.\n function submitRestartProof(\n uint256 profileId,\n bytes calldata tdxReportBody,\n bytes calldata zkProof,\n address newLeader,\n bytes32 checkpointHash\n ) external {\n if (restartGatheringDeadline == 0 || block.timestamp > restartGatheringDeadline) {\n revert GatheringNotActive();\n }\n if (newLeader == address(0)) revert ZeroAddress();\n if (address(automataVerifier) == address(0)) revert InvalidVerifier();\n\n // 1. ZK Verification\n // Assert that the 'tdxReportBody' was indeed generated by a genuine Intel TDX hardware\n // running the code logic proved by the ZK circuit.\n (bool success, bytes memory errorData) = automataVerifier.verifyAndAttestWithZKProof(\n tdxReportBody,\n IAutomataDcapAttestation.ZkCoProcessorType.Succinct, // Opinionated: Use SP1\n zkProof\n );\n\n // Handle failure explicitly\n if (!success) {\n // Forward the error from Automata if possible, or generic revert\n if (errorData.length > 0) {\n assembly {\n let retLen := mload(errorData)\n revert(add(32, errorData), retLen)\n }\n } else {\n revert InvalidZkProof();\n }\n }\n\n // 2. Policy Check (The \"Gold Image\")\n // Verify that the Code Hash (MRTD) inside the verified body matches our governance.\n // MRTD is at offset 136. We take the first 32 bytes of the SHA384.\n if (tdxReportBody.length < 584) revert InvalidQuoteLength();\n bytes32 qMrtd = bytes32(tdxReportBody[136:168]);\n\n // RTMRs start at 328. Stride is 48 bytes.\n bytes32 qRtmr0 = bytes32(tdxReportBody[328:360]);\n bytes32 qRtmr1 = bytes32(tdxReportBody[376:408]);\n bytes32 qRtmr2 = bytes32(tdxReportBody[424:456]);\n bytes32 qRtmr3 = bytes32(tdxReportBody[472:504]);\n\n verifyMeasurements(profileId, qMrtd, qRtmr0, qRtmr1, qRtmr2, qRtmr3);\n\n // 3. Identity Binding\n // Verify that the TEE explicitly committed to this Leader and Checkpoint in ReportData.\n // [Leader (20) | Checkpoint (32) | Epoch (8) | ProcessedCount (4)]\n // Total 64 bytes at Offset 520\n // A. Extract Leader (Bytes 520..540)\n address recoveredLeader = address(bytes20(tdxReportBody[520:540]));\n\n // B. Extract Checkpoint (Bytes 540..572)\n bytes32 recoveredCheckpoint = bytes32(tdxReportBody[540:572]);\n\n // C. Extract Epoch (Bytes 572..580)\n // We read 8 bytes, cast to uint64.\n uint64 recoveredEpoch = uint64(bytes8(tdxReportBody[572:580]));\n\n if (recoveredLeader != newLeader) revert InvalidReportData();\n if (recoveredCheckpoint != checkpointHash) revert InvalidReportData();\n\n // 5. Monotonicity Check\n if (recoveredEpoch <= epoch) {\n revert ProposedEpochTooLow(epoch, recoveredEpoch);\n }\n\n // If this is the first valid candidate\n if (!bestCandidate.exists) {\n bestCandidate = RestartCandidate({\n leader: newLeader,\n epoch: recoveredEpoch,\n checkpointHash: checkpointHash,\n exists: true\n });\n emit RestartCandidateSubmitted(newLeader, recoveredEpoch, checkpointHash);\n return;\n }\n\n // If we already have a candidate, COMPARE.\n\n // Case 1: Proposed Epoch is HIGHER -> Replace Best\n if (recoveredEpoch > bestCandidate.epoch) {\n // Strictly better epoch -> Replace\n bestCandidate = RestartCandidate({\n leader: newLeader,\n epoch: recoveredEpoch,\n checkpointHash: checkpointHash,\n exists: true\n });\n isRestartAmbiguous = false;\n emit RestartCandidateSubmitted(newLeader, recoveredEpoch, checkpointHash);\n }\n // Case 2: Proposed Epoch is EQUAL\n else if (recoveredEpoch == bestCandidate.epoch) {\n // If Hash is DIFFERENT -> SPLIT BRAIN\n if (checkpointHash != bestCandidate.checkpointHash) {\n isRestartAmbiguous = true;\n emit RestartAmbiguityDetected(\n recoveredEpoch, bestCandidate.checkpointHash, checkpointHash\n );\n }\n // If Hash is SAME, ignore (duplicate proposal)\n }\n // Case 3: Proposed Epoch is LOWER -> Ignore\n }\n\n /// @notice Step 3: Finalizes the restart after the window closes.\n function resolveRestart() external {\n if (restartGatheringDeadline == 0) revert GatheringNotActive();\n if (block.timestamp <= restartGatheringDeadline) revert GatheringNotExpired();\n\n if (!bestCandidate.exists) revert NoCandidate();\n if (isRestartAmbiguous) revert AmbiguousState();\n\n // Apply State\n _updateLeader(bestCandidate.leader);\n latestCheckpointHash = bestCandidate.checkpointHash;\n epoch = bestCandidate.epoch;\n\n // Reset Gathering\n restartGatheringDeadline = 0;\n delete bestCandidate;\n\n emit EpochIncremented(epoch, latestCheckpointHash);\n emit RestartExecuted(leader, epoch);\n }\n\n // =============================================================\n // GOVERNANCE VERIFICATION\n // =============================================================\n\n /// @notice Returns the EIP-712 domain separator used for verifying governance signatures.\n /// @return The domain separator hash.\n function domainSeparator() public view returns (bytes32) {\n return keccak256(\n abi.encode(\n _EIP712_DOMAIN_TYPEHASH, _NAME_HASH, _VERSION_HASH, block.chainid, address(this)\n )\n );\n }\n\n /// @dev Reconstructs the signed EIP-712 digest for a specific action.\n function _hashAction(bytes32 opType, bytes32 paramsHash, uint256 nonce)\n internal\n view\n returns (bytes32)\n {\n bytes32 structHash = keccak256(abi.encode(_ACTION_TYPEHASH, opType, paramsHash, nonce));\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator(), structHash));\n }\n\n /// @notice Verifies that a payload has been signed by a valid quorum of operators.\n /// @dev This is the core access control modifier. It verifies:\n /// 1. Sufficient signatures (k of n).\n /// 2. Signers are valid operators.\n /// 3. Signatures are unique and sorted (to prevent duplicates).\n /// 4. The payload matches the expected operation type and parameters.\n /// 5. Increments the nonce to prevent replay attacks.\n /// @param opType The operation identifier (e.g., OP_ADD_VAULT).\n /// @param paramsHash The keccak256 hash of the abi-encoded parameters.\n /// @param signers An array of operator addresses who signed the payload. Must be sorted ascending.\n /// @param signatures An array of signatures corresponding to the signers.\n function _requireQuorum(\n bytes32 opType,\n bytes32 paramsHash,\n address[] calldata signers,\n bytes[] calldata signatures\n ) internal {\n // If sender is admin and no signatures provided, skip verification.\n if (msg.sender == admin && signers.length == 0 && signatures.length == 0) {\n // Increment nonce anyway to simulate state change/prevent strict replays\n unchecked {\n governanceNonce++;\n }\n return;\n }\n uint256 q = quorumThreshold;\n if (signers.length != signatures.length) revert SignersNotSortedOrUnique();\n if (signers.length < q || signatures.length < q) {\n revert InsufficientSignatures(signers.length, q);\n }\n\n bytes32 digest = _hashAction(opType, paramsHash, governanceNonce);\n\n address prev = address(0);\n for (uint256 i = 0; i < q; i++) {\n address signer = signers[i];\n // Enforce sorted order to check for duplicates (O(N) vs O(N^2))\n if (signer <= prev) revert SignersNotSortedOrUnique();\n prev = signer;\n\n if (!isOperator[signer]) revert NotOperator(signer);\n\n // Handles EIP-1271 and EOA signatures.\n if (!signer.isValidSignatureNow(digest, signatures[i])) revert NotOperator(signer);\n }\n\n // Increment nonce to invalidate this hash for future use\n unchecked {\n governanceNonce++;\n }\n }\n\n // =============================================================\n // IMMEDIATE ACTIONS\n // =============================================================\n\n /// @notice Updates the number of signatures required for valid governance actions.\n /// @dev Requires a quorum of the *current* operators to approve.\n /// @param newThreshold The new minimum number of signatures.\n /// @param signers Sorted array of signers.\n /// @param signatures Corresponding signatures.\n function updateQuorumThreshold(\n uint256 newThreshold,\n address[] calldata signers,\n bytes[] calldata signatures\n ) external {\n if (newThreshold == 0 || newThreshold > operators.length) {\n revert InvalidQuorum(newThreshold, operators.length);\n }\n\n bytes32 paramsHash = keccak256(abi.encode(newThreshold));\n _requireQuorum(OP_SET_QUORUM, paramsHash, signers, signatures);\n\n uint256 oldThreshold = quorumThreshold;\n quorumThreshold = newThreshold;\n\n emit QuorumThresholdUpdated(oldThreshold, newThreshold);\n }\n\n /// @notice Registers a new deposit vault to the system.\n /// @dev This list is append-only. New vaults can be added, but existing ones cannot be removed.\n /// @param routingId The routing ID of the vault.\n /// @param vmId The Chain ID for EVM chains requested.\n /// @param vaultAddr The address of the vault (as bytes32).\n /// @param signers Sorted array of signers.\n /// @param signatures Corresponding signatures.\n function addVault(\n uint8 routingId,\n uint256 vmId,\n bytes32 vaultAddr,\n ChainConfig calldata config,\n address[] calldata signers,\n bytes[] calldata signatures\n ) external {\n if (vaultAddr == bytes32(0)) revert InvalidVaultAddr();\n\n bytes32 paramsHash = keccak256(abi.encode(routingId, vmId, vaultAddr, config));\n _requireQuorum(OP_ADD_VAULT, paramsHash, signers, signatures);\n\n vaults.push(\n Vault({routingId: routingId, vmId: vmId, vaultAddress: vaultAddr, config: config})\n );\n emit VaultAdded(routingId, vmId, vaultAddr, config);\n }\n\n /// @notice Registers a strategy contract to handle updates for a specific chain.\n /// @dev Used to define how the Credential Manager talks to L2s (e.g., via bridges).\n /// Only one strategy can be registered per chain.\n /// @param routingId The routing ID of the vault.\n /// @param vmId The Chain ID for EVM chains requested.\n /// @param strategy The address of the strategy contract.\n /// @param signers Sorted array of signers.\n /// @param signatures Corresponding signatures.\n function registerAdminUpdateStrategy(\n uint8 routingId,\n uint256 vmId,\n IAdminUpdateStrategy strategy,\n address[] calldata signers,\n bytes[] calldata signatures\n ) external {\n if (address(strategy) == address(0)) revert ZeroAddress();\n if (address(adminUpdateStrategies[routingId][vmId]) != address(0)) {\n revert StrategyAlreadyExists();\n }\n\n bytes32 paramsHash = keccak256(abi.encode(routingId, vmId, address(strategy)));\n _requireQuorum(OP_REGISTER_STRATEGY, paramsHash, signers, signatures);\n\n adminUpdateStrategies[routingId][vmId] = strategy;\n emit AdminUpdateStrategyRegistered(routingId, vmId, address(strategy));\n }\n\n /// @notice Updates the administrators or withdrawal quorum for a vault on a remote chain.\n /// @dev This function acts as a proxy. It verifies the operator quorum locally, then\n /// delegate-calls the strategy to execute the actual logic (e.g., sending an L1->L2 message).\n /// @param routingId The routing ID of the vault.\n /// @param vmId The Chain ID for EVM chains requested.\n /// @param newAdministrators The list of new admin addresses for that vault.\n /// @param newWithdrawalQuorum The new quorum requirement for that vault.\n /// @param signers Sorted array of signers.\n /// @param signatures Corresponding signatures.\n function setDepositVaultAdministrators(\n uint256 routingId,\n uint256 vmId,\n address[] calldata newAdministrators,\n uint256 newWithdrawalQuorum,\n address[] calldata signers,\n bytes[] calldata signatures\n ) external payable {\n IAdminUpdateStrategy strategy = adminUpdateStrategies[routingId][vmId];\n if (address(strategy) == address(0)) revert NoStrategy();\n\n // Include msg.value in hash to prevent replay attacks where a signature for a 0-fee\n // transaction is replayed on a high-fee transaction.\n bytes32 paramsHash = keccak256(\n abi.encode(routingId, vmId, newAdministrators, newWithdrawalQuorum, msg.value)\n );\n _requireQuorum(OP_SET_VAULT_ADMINS, paramsHash, signers, signatures);\n\n // Delegatecall allows this contract to retain its identity (msg.sender) when calling the bridge.\n (bool ok,) = address(strategy)\n .delegatecall(\n abi.encodeWithSelector(\n strategy.setAdministrators.selector,\n _getVaultAddress(routingId, vmId),\n newAdministrators,\n newWithdrawalQuorum\n )\n );\n require(ok, \"Strategy delegatecall failed\");\n emit DepositVaultAdministratorsUpdated(\n routingId, vmId, newAdministrators, newWithdrawalQuorum\n );\n }\n\n /// @notice Withdraw funds held by this contract.\n function withdraw(address account, address[] calldata signers, bytes[] calldata signatures)\n external\n {\n if (account == address(0)) revert ZeroAddress();\n bytes32 paramsHash = keccak256(abi.encode(account, address(this).balance));\n _requireQuorum(OP_WITHDRAW, paramsHash, signers, signatures);\n payable(account).transfer(address(this).balance);\n }\n\n // =============================================================\n // VIEW HELPERS\n // =============================================================\n\n /// @notice Returns a paginated list of registered vaults.\n /// @dev The input types are intentionally `uint16` to preserve the function selector\n /// `0x9fd7285c` for backward compatibility with existing Rust clients.\n /// @param start The start index.\n /// @param end The end index (exclusive).\n /// @return An array of Vault structs.\n function getVaults(uint16 start, uint16 end) external view returns (Vault[] memory) {\n uint256 count = vaults.length;\n if (start >= count) return new Vault[](0);\n if (end > count) end = uint16(count);\n if (end <= start) return new Vault[](0);\n\n uint256 len = uint256(end - start);\n Vault[] memory out = new Vault[](len);\n for (uint256 i = 0; i < len; i++) {\n out[i] = vaults[uint256(start) + i];\n }\n return out;\n }\n\n function _getVaultAddress(uint256 routingId, uint256 vmId) internal view returns (address) {\n uint256 len = vaults.length;\n for (uint256 i; i < len; ++i) {\n Vault memory vault = vaults[i];\n if (vault.routingId == routingId && vault.vmId == vmId) {\n // Convert bytes32 to address (assuming left-aligned or standard encoding).\n // Shifts right 96 bits to recover the 160-bit address if it was stored left-aligned.\n return address(uint160(uint256(vault.vaultAddress >> 96)));\n }\n }\n revert VaultNotFound(routingId, vmId);\n }\n\n // =============================================================\n // TIMELOCKED ACTIONS\n // =============================================================\n\n /// @notice Schedules a timelocked update for the Risk Manager address.\n /// @dev The operation cannot be executed until `TIMELOCK_DELAY` has passed.\n /// @param newRiskManager The proposed new Risk Manager address.\n /// @return opId The unique hash of the scheduled operation.\n function scheduleRiskManager(\n address newRiskManager,\n address[] calldata signers,\n bytes[] calldata signatures\n ) external returns (bytes32 opId) {\n if (newRiskManager == address(0)) revert ZeroAddress();\n bytes32 paramsHash = keccak256(abi.encode(newRiskManager));\n _requireQuorum(OP_SET_RISK_MANAGER, paramsHash, signers, signatures);\n opId = _schedule(OP_SET_RISK_MANAGER, paramsHash);\n }\n\n /// @notice Executes a pending Risk Manager update if the timelock has expired.\n /// @param newRiskManager The address that was previously scheduled.\n function executeRiskManager(address newRiskManager) external {\n if (newRiskManager == address(0)) revert ZeroAddress();\n bytes32 paramsHash = keccak256(abi.encode(newRiskManager));\n bytes32 opId = _opId(OP_SET_RISK_MANAGER, paramsHash);\n\n _executeTimelock(opId);\n\n address old = riskManager;\n riskManager = newRiskManager;\n emit OperationExecuted(opId, OP_SET_RISK_MANAGER);\n emit RiskManagerUpdated(old, newRiskManager);\n }\n\n /// @notice Schedules a timelocked update for the Registry Contract address.\n /// @param newRegistry The proposed new Registry address.\n /// @return opId The unique hash of the scheduled operation.\n function scheduleRegistryContract(\n address newRegistry,\n address[] calldata signers,\n bytes[] calldata signatures\n ) external returns (bytes32 opId) {\n if (newRegistry == address(0)) revert ZeroAddress();\n bytes32 paramsHash = keccak256(abi.encode(newRegistry));\n _requireQuorum(OP_SET_REGISTRY, paramsHash, signers, signatures);\n opId = _schedule(OP_SET_REGISTRY, paramsHash);\n }\n\n /// @notice Executes a pending Registry Contract update if the timelock has expired.\n /// @param newRegistry The address that was previously scheduled.\n function executeRegistryContract(address newRegistry) external {\n if (newRegistry == address(0)) revert ZeroAddress();\n bytes32 paramsHash = keccak256(abi.encode(newRegistry));\n bytes32 opId = _opId(OP_SET_REGISTRY, paramsHash);\n\n _executeTimelock(opId);\n\n address old = registryContract;\n registryContract = newRegistry;\n emit OperationExecuted(opId, OP_SET_REGISTRY);\n emit RegistryUpdated(old, newRegistry);\n }\n\n // Timelocked measurement actions\n\n /// @notice Validates measurements against a specific approved Profile.\n /// @dev Supports \"Partial Matching\": If the Profile has bytes32(0) for an RTMR,\n /// skips checking that specific register (accommodating different provider patterns).\n function verifyMeasurements(\n uint256 profileId,\n bytes32 checkMrtd,\n bytes32 checkRtmr0,\n bytes32 checkRtmr1,\n bytes32 checkRtmr2,\n bytes32 checkRtmr3\n ) internal view {\n MeasurementProfile memory profile = measurementProfiles[profileId];\n\n if (!profile.active) revert ProfileInactive(profileId);\n if (profile.mrtd == bytes32(0)) revert ZeroAddress();\n\n // MRTD is always mandatory\n if (checkMrtd != profile.mrtd) revert MeasurementMismatch(profile.mrtd, checkMrtd, \"MRTD\");\n\n // RTMRs are conditional based on the Profile configuration\n if (profile.rtmr0 != bytes32(0) && checkRtmr0 != profile.rtmr0) {\n revert MeasurementMismatch(profile.rtmr0, checkRtmr0, \"RTMR0\");\n }\n\n if (profile.rtmr1 != bytes32(0) && checkRtmr1 != profile.rtmr1) {\n revert MeasurementMismatch(profile.rtmr1, checkRtmr1, \"RTMR1\");\n }\n\n if (profile.rtmr2 != bytes32(0) && checkRtmr2 != profile.rtmr2) {\n revert MeasurementMismatch(profile.rtmr2, checkRtmr2, \"RTMR2\");\n }\n\n if (profile.rtmr3 != bytes32(0) && checkRtmr3 != profile.rtmr3) {\n revert MeasurementMismatch(profile.rtmr3, checkRtmr3, \"RTMR3\");\n }\n }\n\n /// @notice Governance proposes adding or updating a measurement profile (e.g., for Phala or GCP).\n function scheduleManageProfile(\n uint256 profileId,\n MeasurementProfile calldata profile,\n address[] calldata signers,\n bytes[] calldata signatures\n ) external returns (bytes32 opId) {\n // Anti-Bricking: MRTD must never be zero if activating\n if (profile.active && profile.mrtd == bytes32(0)) revert InvalidVaultAddr();\n\n bytes32 paramsHash = keccak256(abi.encode(profileId, profile));\n _requireQuorum(OP_MANAGE_PROFILE, paramsHash, signers, signatures);\n opId = _schedule(OP_MANAGE_PROFILE, paramsHash);\n }\n\n function executeManageProfile(uint256 profileId, MeasurementProfile calldata profile) external {\n bytes32 paramsHash = keccak256(abi.encode(profileId, profile));\n bytes32 opId = _opId(OP_MANAGE_PROFILE, paramsHash);\n\n _executeTimelock(opId);\n\n // Auto-increment ID if adding a new one with ID 0\n uint256 idToUpdate = profileId;\n if (idToUpdate == 0) {\n idToUpdate = nextProfileId++;\n }\n\n measurementProfiles[idToUpdate] = profile;\n emit OperationExecuted(opId, OP_MANAGE_PROFILE);\n emit MeasurementProfileUpdated(idToUpdate, profile.active);\n }\n\n /// @notice Sxecudes a timelocked update for the Automata Verifier address.\n function executeUpdateAutomataVerifier(address newVerifier) external {\n if (newVerifier == address(0)) revert ZeroAddress();\n bytes32 paramsHash = keccak256(abi.encode(newVerifier));\n bytes32 opId = _opId(OP_SET_AUTOMATA_VERIFIER, paramsHash);\n _executeTimelock(opId);\n\n address old = address(automataVerifier);\n automataVerifier = IAutomataDcapAttestation(newVerifier);\n\n emit OperationExecuted(opId, OP_SET_AUTOMATA_VERIFIER);\n emit AutomataVerifierUpdated(old, newVerifier);\n }\n\n /// @notice Schedules a timelocked update for the Automata Verifier.\n /// @dev Operators vote to update the verifier and the update is proposed with a timelocked delay.\n function scheduleUpdateAutomataVerifier(\n address newVerifier,\n address[] calldata signers,\n bytes[] calldata signatures\n ) external returns (bytes32 opId) {\n if (newVerifier == address(0)) revert ZeroAddress();\n bytes32 paramsHash = keccak256(abi.encode(newVerifier));\n _requireQuorum(OP_SET_AUTOMATA_VERIFIER, paramsHash, signers, signatures);\n opId = _schedule(OP_SET_AUTOMATA_VERIFIER, paramsHash);\n }\n\n // Timelock cancellation\n\n /// @notice Cancels a pending timelocked operation.\n /// @dev Can be called at any time before execution to prevent a malicious or erroneous update.\n /// @param opId The hash of the operation to cancel.\n function cancelTimelock(bytes32 opId, address[] calldata signers, bytes[] calldata signatures)\n external\n {\n bytes32 paramsHash = keccak256(abi.encode(opId));\n _requireQuorum(OP_CANCEL_TIMELOCK, paramsHash, signers, signatures);\n\n TimelockOp storage op = timelockOps[opId];\n if (op.eta == 0) revert TimelockUnknown(opId);\n if (op.executed) revert TimelockAlreadyExecuted(opId);\n if (op.canceled) revert TimelockAlreadyCanceled(opId);\n\n op.canceled = true;\n emit OperationCanceled(opId, op.opType);\n }\n\n // =============================================================\n // TIMELOCK INTERNAL LOGIC\n // =============================================================\n\n /// @dev Deterministically generates the operation ID hash.\n function _opId(bytes32 opType, bytes32 paramsHash) internal view returns (bytes32) {\n return keccak256(abi.encode(opType, paramsHash, address(this), block.chainid));\n }\n\n /// @dev Internal helper to schedule an operation.\n function _schedule(bytes32 opType, bytes32 paramsHash) internal returns (bytes32 opId) {\n opId = _opId(opType, paramsHash);\n TimelockOp storage op = timelockOps[opId];\n if (op.executed) revert TimelockAlreadyExecuted(opId);\n\n uint256 delay = timelockDelayFor[opType];\n if (delay == 0) revert InvalidDelay(delay);\n\n uint64 eta = uint64(block.timestamp + delay);\n op.eta = eta;\n op.executed = false;\n op.canceled = false;\n op.opType = opType;\n emit OperationScheduled(opId, opType, eta);\n }\n\n /// @dev Internal helper to validate if an operation is ready for execution.\n function _executeTimelock(bytes32 opId) internal {\n TimelockOp storage op = timelockOps[opId];\n if (op.eta == 0) revert TimelockUnknown(opId);\n if (op.executed) revert TimelockAlreadyExecuted(opId);\n if (op.canceled) revert TimelockAlreadyCanceled(opId);\n if (block.timestamp < op.eta) revert TimelockNotReady(opId, op.eta, block.timestamp);\n op.executed = true;\n }\n\n /// @notice Allows the contract to receive ETH (needed for strategies that require fees).\n receive() external payable {}\n}\n","urls":[]},"src/DepositVault.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {SafeTransferLib} from \"solady/utils/SafeTransferLib.sol\";\nimport {EfficientHashLib} from \"solady/utils/EfficientHashLib.sol\";\nimport {ECDSA} from \"solady/utils/ECDSA.sol\";\nimport {IAtomicSettlementCallback} from \"./interfaces/IAtomicSettlementCallback.sol\";\n\ncontract DepositVault {\n /**\n * @notice The admin approves settlements and withdrawals.\n * @dev Should be set to the DStack container shared secret address.\n */\n address public owner;\n\n /**\n * @notice The address responsible for adding or removing administrators\n * @dev In production, this will be an upgradeable proxy\n */\n address public credentialManager;\n\n /// @notice Domain separator used for signature verification. It should include the routing ID, the vm ID, this\n /// vault address, and the settlement schema version.\n bytes32 internal _domainSeparator;\n\n /// @notice Maps settler IDs to their executor addresses.\n mapping(bytes32 => SettlerInfo) settlerExecutorMap;\n\n /// @notice List of all approved settler IDs.\n bytes32[] public approvedSettlers;\n\n /// @notice Minimum number of administrator signatures to approve a withdrawal request\n uint256 public withdrawalQuorum;\n\n uint256 public credentialManagerChangeDelayBlocks = 14400;\n\n /// @notice Tracks which settler IDs have been approved.\n mapping(bytes32 => bool) internal settlerIsApproved;\n\n /**\n * @notice Maximum total tokens that can be settled in a single block for each token.\n * @dev Currently unused \u2014 implementation pending design finalization.\n */\n mapping(address => uint256) public settlementCaps;\n\n /// @notice Maps (settler ID, account_index) pairs to their queue of pending batch settlements.\n mapping(bytes32 => mapping(uint64 => PendingSettlement[])) public pendingSettlements;\n\n /// @notice Maps (settler ID, account_index) pairs to their settlement count (nonce).\n mapping(bytes32 => mapping(uint64 => uint256)) public settlementCounts;\n\n /// @notice Maps (settler ID, account_index) pairs to their deposit count (nonce).\n mapping(bytes32 => mapping(uint64 => uint256)) public depositCounts;\n\n /// @notice Maps (settler ID, account_index) pairs to their withdrawal count (nonce).\n mapping(bytes32 => mapping(uint64 => uint256)) public withdrawalCounts;\n\n /// @notice Set of administrators\n address[] public administrators;\n\n // TODO: Delete before official production.\n mapping(address => bool) public canDeposit;\n\n /// @notice Block number of latest signature use\n uint256 public lastSignatureUse;\n\n /**\n * Makes the signature unambiguous that it is for settlements.\n */\n bytes32 constant SETTLEMENT_TYPEHASH = keccak256(\"SettlementApprovalV1\");\n\n /**\n * Makes the signature unambiguous that it is for withdrawals.\n */\n bytes32 constant WITHDRAWAL_TYPEHASH = keccak256(\"WithdrawalApprovalV1\");\n\n /**\n * @notice A single settlement request for token swaps.\n * @dev Used in both atomic and batch settlements.\n */\n struct Settlement {\n address tokenOut;\n uint256 amountOut;\n address tokenIn;\n uint256 amountIn;\n uint256 nonce;\n }\n\n /// @notice A settlement plus an off-chain signature from an authorized party.\n struct SignedSettlement {\n Settlement settlement;\n bytes signature;\n }\n\n /**\n * @notice Stores pending settlements for a given (user ID, account_index) pair when batch settlement is used.\n * @dev Target is the address expected to execute the settlement.\n */\n struct PendingSettlement {\n Settlement settlement;\n address target;\n }\n\n /// @notice Records a withdrawal.\n struct Withdrawal {\n address tokenAddress;\n uint256 amount;\n uint256 nonce;\n }\n\n /// @notice Information about a settler account.\n struct SettlerInfo {\n address[] executors;\n mapping(address => bool) isExecutor;\n }\n\n /// @notice Signals a settlement.\n event Settled(\n bytes32 indexed user,\n uint64 indexed account,\n uint256 indexed nonce,\n address tokenOut,\n uint256 amountOut,\n address tokenIn,\n uint256 amountIn\n );\n\n /// @notice Indicates that the set of administrators has been cleared and is now empty\n event AdministratorSetReset();\n\n /// @notice Signals that the withdrawal quorum has changed\n event WithdrawalQuorumChanged(uint256 previous, uint256 current);\n\n /// @notice Signals that the credential manager address has changed\n event CredentialManagerChanged(address oldCredentialManager, address newCredentialManager);\n\n /// @notice Signals that a new administrator has been added to the vault\n event AdminAdded(address newAdmin, uint256 numAdminsAfter);\n\n /// @notice Signals a deposit.\n event Deposited(\n bytes32 indexed user,\n uint64 indexed account,\n uint256 indexed nonce,\n address tokenAddress,\n uint256 amount\n );\n\n /// @notice Signals a withdrawal.\n event Withdrew(\n bytes32 indexed user,\n uint64 indexed account,\n uint256 indexed nonce,\n address tokenAddress,\n uint256 amount\n );\n\n /// @notice Reverts if the caller is not the owner.\n error NotOwner();\n\n /// @notice Reverts if a settlement callback returns an insufficient input token amount\n error InsufficientAmountFromExecutor(uint256 actual, uint256 required);\n\n /// @notice Reverts if an insufficient number of blocks have elapsed since the last signature use\n error TooSoon();\n\n /// @notice Reverts if the caller is not the credential manager\n error NotCredentialManager();\n\n /// @notice Reverts if a new withdrawal quorum value is equal to zero\n error ZeroWithdrawalQuorum();\n\n /// @notice Reverts if insufficient administrators are provided when setting the administrators\n error InsufficientAdministrators(uint256 actual, uint256 required);\n\n /// @notice Reverts if the caller is not an admin.\n error NotAdmin();\n\n /// @notice Reverts if the caller is not the authorized executor.\n error NotExecutor();\n\n /// @notice Reverts if a signed operation is past its deadline.\n error Expired();\n\n /// @notice Reverts if the nonce used in a transaction is incorrect.\n error InvalidNonce(uint256 expected, uint256 given);\n\n /// @notice Reverts if the signature provided is invalid.\n error InvalidSignature();\n\n /// @notice Reverts if an order array is empty.\n error EmptyOrders();\n\n /// @notice Reverts when given the zero address.\n error ZeroAddress();\n\n /// @notice Reverts when an insufficient number of signatures are provided for a withdrawal request\n error MissedQuorum(uint256 provided, uint256 required);\n\n /**\n * @notice Initializes the contract and sets the owner.\n * @param _owner The address to set as the owner.\n * @param _credentialManager The address of the credential manager.\n * @dev Reverts with `ZeroAddress()` if `_owner` is null.\n * @dev Reverts with `ZeroAddress()` if `_credentialManager` is null.\n */\n constructor(address _owner, address _credentialManager) {\n if (_owner == address(0)) revert ZeroAddress();\n if (_credentialManager == address(0)) revert ZeroAddress();\n owner = _owner;\n credentialManager = _credentialManager;\n }\n\n function isAdministrator(address account) public view returns (bool) {\n for (uint256 i = 0; i < administrators.length; i++) {\n if (administrators[i] == account) return true;\n }\n\n return false;\n }\n\n /**\n * @notice Sets the owner of the vault.\n * @dev Reverts with `NotOwner`; Only the owner can set a new owner.\n */\n function setOwner(address newOwner) external {\n if (msg.sender != owner) revert NotOwner();\n if (newOwner == address(0)) revert ZeroAddress();\n owner = newOwner;\n }\n\n function setCredentialManager(address newCredentialManager) external {\n if (msg.sender != owner) revert NotOwner();\n if (newCredentialManager == address(0)) revert ZeroAddress();\n /* TODO(jmcph4): check against `latestApproval`! */\n if (block.number >= lastSignatureUse + credentialManagerChangeDelayBlocks) {\n revert TooSoon();\n }\n address oldCredentialManager = credentialManager;\n credentialManager = newCredentialManager;\n emit CredentialManagerChanged(oldCredentialManager, newCredentialManager);\n }\n\n function setAdministrators(address[] calldata newAdministrators, uint256 newWithdrawalQuorum)\n external\n {\n if (msg.sender != credentialManager) revert NotCredentialManager();\n if (newWithdrawalQuorum < 1) revert ZeroWithdrawalQuorum();\n if (newAdministrators.length < newWithdrawalQuorum) {\n revert InsufficientAdministrators(newAdministrators.length, newWithdrawalQuorum);\n }\n\n // It's critical there are no zero-addresses; otherwise, errored signatures may mistakenly pass.\n for (uint256 i = 0; i < newAdministrators.length; i++) {\n if (newAdministrators[i] == address(0)) revert ZeroAddress();\n }\n\n administrators = newAdministrators;\n emit AdministratorSetReset();\n\n for (uint256 i = 0; i < administrators.length; i++) {\n address currAdmin = administrators[i];\n emit AdminAdded(currAdmin, i + 1);\n }\n\n uint256 oldWithdrawalQuorum = withdrawalQuorum;\n withdrawalQuorum = newWithdrawalQuorum;\n if (oldWithdrawalQuorum != newWithdrawalQuorum) {\n emit WithdrawalQuorumChanged(oldWithdrawalQuorum, newWithdrawalQuorum);\n }\n }\n\n /**\n * @notice Sets the domain separators for EIP-712 signatures.\n * @param domainSeparator: The value to set.\n * @dev Reverts with `NotOwner`; Only the admin can set the domain separator.\n */\n function setDomainSeparator(bytes32 domainSeparator) external {\n if (msg.sender != owner) revert NotOwner();\n require(_domainSeparator == 0); // dev: Already set.\n _domainSeparator = domainSeparator;\n }\n\n /**\n * @notice Sets the settle executor.\n * @param settler: The settler's tplus account key.\n * @param executor: The settler's assigned executor address.\n * @dev Reverts with `NotOwner`; Only the admin can set the settler executor.\n */\n function addSettlerExecutor(bytes32 settler, address executor) external {\n if (msg.sender != owner) revert NotOwner();\n\n if (!settlerIsApproved[settler]) {\n approvedSettlers.push(settler);\n settlerIsApproved[settler] = true;\n }\n\n SettlerInfo storage data = settlerExecutorMap[settler];\n if (!data.isExecutor[executor]) {\n data.executors.push(executor);\n data.isExecutor[executor] = true;\n }\n }\n\n /**\n * @notice Removes a settler.\n * @param settler: The settler's tplus account key.\n * @dev Reverts with `NotOwner`; Only the admin can remove a settler.\n */\n function removeSettler(bytes32 settler) external {\n if (msg.sender != owner) revert NotOwner();\n uint256 length = approvedSettlers.length;\n\n settlerIsApproved[settler] = false;\n\n for (uint256 i = 0; i < length; i++) {\n if (approvedSettlers[i] == settler) {\n // Move last element to this spot and pop the last element.\n approvedSettlers[i] = approvedSettlers[length - 1];\n approvedSettlers.pop();\n break;\n }\n }\n\n // Remove all executors.\n SettlerInfo storage info = settlerExecutorMap[settler];\n for (uint256 i = 0; i < info.executors.length; i++) {\n address exec = info.executors[i];\n info.isExecutor[exec] = false;\n }\n delete info.executors;\n }\n\n /**\n * @notice Deposits a token into the vault.\n * @param user: The user whose account will be credited with the deposit.\n * @param account: The account index of the specified user that will be credited with the deposit\n * @param tokenAddress: The address of the token to deposit.\n * @param amount: The amount of the token to deposit.\n * @dev Reverts if the amount is 0.\n */\n function deposit(bytes32 user, uint64 account, address tokenAddress, uint256 amount) external {\n require(canDeposit[msg.sender], \"!depositor\");\n require(amount != 0, \"Zero\");\n\n // Move tokens from the target user to this vault.\n SafeTransferLib.safeTransferFrom(tokenAddress, msg.sender, address(this), amount);\n\n emit Deposited(user, account, depositCounts[user][account], tokenAddress, amount);\n depositCounts[user][account] += 1;\n }\n\n // TODO: Delete this method and notion of approved-depositor before official production.\n function setDepositorStatus(address depositor, bool allowed) external {\n if (msg.sender != owner) revert NotOwner();\n canDeposit[depositor] = allowed;\n }\n\n /**\n * @notice Executes an atomic settlement.\n * @param order: The settlement order.\n * @param user: The t+ user who is executing the settlement.\n * @param account: The account index of the t+ user that will be used for settlement\n * @param validUntil: How long until the signature expires.\n * @param data: The data to execute as part of settlement callback.\n * @param signature: The signature from the t+ clearing engine.\n * @dev Reverts with `Expired` if the block timestamp is greater than `validUntil`.\n * @dev Reverts with `NotExecutor`; Only the executor can settle.\n * @dev Reverts with `InvalidNonce` if the nonce has already been used.\n * @dev Reverts with `SignatureError` if the signer is not an admin.\n * @dev Reverts with `InsufficientAmountFromExecutor` if the `order.amountIn` is less than what the executor reports\n */\n function executeAtomicSettlement(\n Settlement calldata order,\n bytes32 user,\n uint64 account,\n uint256 validUntil,\n bytes calldata data,\n bytes calldata signature\n ) external {\n if (block.timestamp > validUntil) revert Expired();\n if (!settlerExecutorMap[user].isExecutor[msg.sender]) revert NotExecutor();\n\n uint256 expectedNonce = settlementCounts[user][account];\n if (order.nonce != expectedNonce) revert InvalidNonce(expectedNonce, order.nonce);\n\n bytes32 digest = keccak256(\n bytes.concat(\n SETTLEMENT_TYPEHASH,\n _domainSeparator,\n bytes32(uint256(uint160(order.tokenOut)) << 96),\n bytes32(order.amountOut),\n bytes32(uint256(uint160(order.tokenIn)) << 96),\n bytes32(order.amountIn),\n user,\n bytes32(uint256(uint160(account))),\n bytes32(order.nonce),\n bytes32(validUntil)\n )\n );\n\n // Check the signature and record latest signature usage if it's valid\n checkApproval(digest, signature);\n lastSignatureUse = block.number;\n\n // Ensure to bump the nonce _before_ the callback to avoid signature replay.\n settlementCounts[user][account] += 1;\n\n // Invoke callback on the executor\n uint256 expectedAmountIn = IAtomicSettlementCallback(msg.sender)\n .onAtomicSettlement(order.tokenOut, order.amountOut, data);\n if (expectedAmountIn < order.amountIn) {\n revert InsufficientAmountFromExecutor(expectedAmountIn, order.amountIn);\n }\n\n // Transfer tokens IN from the executor\n SafeTransferLib.safeTransferFrom(order.tokenIn, msg.sender, address(this), expectedAmountIn);\n\n // Transfer tokens OUT to the executor\n SafeTransferLib.safeTransfer(order.tokenOut, msg.sender, order.amountOut);\n\n emit Settled(\n user,\n account,\n order.nonce,\n order.tokenOut,\n order.amountOut,\n order.tokenIn,\n order.amountIn\n );\n }\n\n /**\n * @notice Pulls funds for execution during a settlement batch.\n * @param orders: The settlement orders.\n * @param user: The t+ user who is executing the settlement.\n * @param target: The target address to send the token to, pull tokens from, and execute callback on.\n * @param validUntil: The timestamp when the settlement signature expires.\n * @dev Reverts with `Expired` if the block timestamp is greater than `validUntil`.\n * @dev Reverts if a batch settlement has already started.\n * @dev Reverts with `NotAdmin`; Only an admin can execute the settlement.\n * @dev Reverts with `InvalidNonce` if the nonce has already been used.\n * @dev Reverts with `SignatureError` if the signer is not an admin.\n */\n function pullBatchSettlement(\n SignedSettlement[] calldata orders,\n bytes32 user,\n uint64 account,\n address target,\n uint256 validUntil\n ) external {\n if (block.timestamp > validUntil) revert Expired();\n require(pendingSettlements[user][account].length == 0);\n if (!isAdministrator(msg.sender)) revert NotAdmin();\n\n uint256 expectedNonce = settlementCounts[user][account];\n bytes32 domainSeparator = _domainSeparator;\n uint256 ordersLength = orders.length;\n if (ordersLength == 0) revert EmptyOrders();\n\n for (uint256 i = 0; i < ordersLength; ++i) {\n Settlement calldata s = orders[i].settlement;\n\n uint256 nonce = s.nonce;\n if (nonce != expectedNonce) revert InvalidNonce(expectedNonce, nonce);\n\n bytes32 digest = keccak256(\n bytes.concat(\n SETTLEMENT_TYPEHASH,\n domainSeparator,\n bytes32(uint256(uint160(s.tokenOut)) << 96),\n bytes32(s.amountOut),\n bytes32(uint256(uint160(s.tokenIn)) << 96),\n bytes32(s.amountIn),\n user,\n bytes32(uint256(uint160(account))),\n bytes32(s.nonce),\n bytes32(validUntil)\n )\n );\n\n checkApproval(digest, orders[i].signature);\n expectedNonce = nonce + 1;\n\n pendingSettlements[user][account].push(\n PendingSettlement({settlement: s, target: target})\n );\n SafeTransferLib.safeTransfer(s.tokenOut, target, s.amountOut);\n }\n\n settlementCounts[user][account] += ordersLength;\n }\n\n /**\n * @notice Pushes expected funds from a batch settlement to the deposit vault.\n * @param user: The t+ user who is executing the settlement.\n * @param account: The account of the t+ user to execute settlement against\n * @dev Reverts with `NotAdmin`; Only an admin can execute the settlement.\n */\n function pushBatchSettlements(bytes32 user, uint64 account) external {\n if (!isAdministrator(msg.sender)) revert NotAdmin();\n\n for (uint32 i = 0; i < pendingSettlements[user][account].length; i++) {\n PendingSettlement memory pendingSettlement = pendingSettlements[user][account][i];\n\n SafeTransferLib.safeTransferFrom(\n pendingSettlement.settlement.tokenIn,\n pendingSettlement.target,\n address(this),\n pendingSettlement.settlement.amountIn\n );\n emit Settled(\n user,\n account,\n pendingSettlement.settlement.nonce,\n pendingSettlement.settlement.tokenOut,\n pendingSettlement.settlement.amountOut,\n pendingSettlement.settlement.tokenIn,\n pendingSettlement.settlement.amountIn\n );\n }\n delete pendingSettlements[user][account];\n }\n\n /**\n * @notice Withdraws a token from the vault.\n * @param withdrawal: The withdrawal token and amount.\n * @param user: The user whose account will be debited by the withdrawal.\n * @param account: The account of the t+ user that will be debited by the withdrawal.\n * @param target: The target address to send the token to.\n * @param validUntil: The timestamp when the withdrawal signature expires.\n * @param signatures: t+ clearing engine signatures.\n * @dev Reverts with `Expired` if the block timestamp is greater than `validUntil`.\n * @dev Reverts with `InvalidNonce` if the nonce has already been used.\n * @dev Reverts with `SignatureError` if the signer is not an admin.\n */\n function withdraw(\n Withdrawal calldata withdrawal,\n bytes32 user,\n uint64 account,\n address target,\n uint256 validUntil,\n bytes32 epochHash,\n bytes[] calldata signatures\n ) external {\n /* PERF(jmcph4): cache storage variable to the stack */\n uint256 quorum = withdrawalQuorum;\n if (block.timestamp > validUntil) revert Expired();\n if (signatures.length < withdrawalQuorum) {\n revert MissedQuorum(signatures.length, quorum);\n }\n\n uint256 expectedNonce = withdrawalCounts[user][account];\n if (withdrawal.nonce != expectedNonce) {\n revert InvalidNonce(expectedNonce, withdrawal.nonce);\n }\n\n /**\n * BEGIN SIGNATURE CHECKS *************************\n */\n\n // Set of administrators that have provided signatures for this withdrawal\n address[] memory seenAdmins = new address[](signatures.length);\n uint256 numSeenAdmins = 0;\n\n // PERF(jmcph4): No need to recompute inside the loop body\n bytes32 digest = keccak256(\n bytes.concat(\n WITHDRAWAL_TYPEHASH,\n _domainSeparator,\n bytes32(uint256(uint160((withdrawal.tokenAddress))) << 96),\n bytes32(withdrawal.amount),\n user,\n bytes32(withdrawal.nonce),\n bytes32(validUntil),\n bytes32(epochHash),\n bytes32(uint256(uint160(target)) << 96)\n )\n );\n\n for (uint256 i = 0; i < signatures.length; i++) {\n /* Verify the signature.\n *\n * This determines whether the digest is really signed by the provided\n * signature and computes the signer's address.\n */\n address signer = ECDSA.tryRecoverCalldata(digest, signatures[i]);\n if (signer == address(0)) revert InvalidSignature();\n\n // Check that the recovered signer is in fact an administrator\n if (!isAdministrator(signer)) revert InvalidSignature();\n\n /* Check that this administrator is unique. Without this step, a\n * single admin could provide `k` signatures where `k == withdrawalQuorum`\n * and we'd happily approve the withdrawal.\n */\n bool isCurrentSignerUnique = true;\n for (uint256 j = 0; j < numSeenAdmins; j++) {\n if (seenAdmins[j] == signer) {\n isCurrentSignerUnique = false;\n break;\n }\n }\n if (isCurrentSignerUnique) {\n seenAdmins[numSeenAdmins] = signer;\n numSeenAdmins++;\n }\n if (numSeenAdmins == quorum) break;\n }\n\n if (numSeenAdmins < quorum) revert MissedQuorum(numSeenAdmins, quorum);\n\n /**\n * END SIGNATURE CHECKS *************************\n */\n\n // SAFETY(jmcph4): Purposely bump the nonce as close to signature verification as possible, to alleviate callback concerns.\n withdrawalCounts[user][account] += 1;\n\n // Record latest signature usage\n lastSignatureUse = block.number;\n\n SafeTransferLib.safeTransfer(withdrawal.tokenAddress, target, withdrawal.amount);\n emit Withdrew(user, account, withdrawal.nonce, withdrawal.tokenAddress, withdrawal.amount);\n }\n\n /**\n * @notice Get the array of approved settlers.\n * @return An array of addresses (as bytes32) that are currently approved settlers.\n */\n function getApprovedSettlers() external view returns (bytes32[] memory) {\n return approvedSettlers;\n }\n\n // TODO: Delete this method before official production.\n function ownerWithdrawToken(address token, address to, uint256 amount) external {\n if (msg.sender != owner) revert NotOwner();\n require(to != address(0));\n SafeTransferLib.safeTransfer(token, to, amount);\n }\n\n function checkApproval(bytes32 digest, bytes calldata signature) internal view {\n address signer = ECDSA.tryRecoverCalldata(digest, signature);\n if (!isAdministrator(signer)) revert InvalidSignature();\n }\n}\n","urls":[]},"src/Registry.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/**\n * @title Registry\n * @notice Central registry for managing assets and associated risk parameters across multiple chains.\n * @dev Uses admin and multisig roles to control sensitive operations like asset registration and risk configuration.\n */\ncontract Registry {\n /// @notice Address of the admin; primarily used for initial setup.\n address public admin;\n\n /// @notice Multisig wallet address responsible for managing risk-related configurations.\n address public riskManagerMultisig;\n\n /// @notice Number of seconds to wait before new risk parameters become effective\n uint256 public riskParameterChangeDelaySeconds = 1 days;\n\n /// @notice Mapping of asset index to new risk parameters to be applied to the registry, but only after they become eligible\n mapping(uint16 => PendingRiskParameters) public pendingRiskParameters;\n\n /// @notice Mapping of asset index to associated risk parameters.\n mapping(uint16 => RiskParameters) public riskParameters;\n\n /// @notice Registry of all registered assets and associated chain data.\n AssetRegistry assets;\n\n /// @notice Account for receiving fees and paying rewards.\n bytes32 public feeAccount;\n\n /// @notice Signals that the maximum deposit has changed for a given asset\n event MaxDepositChanged(ChainId chain, uint16 index, uint256 previous, uint256 current);\n\n /// @notice Signals that the maximum hourly deposit has changed for a given asset\n event Max1HrDepositChanged(ChainId chain, uint16 index, uint256 previous, uint256 current);\n\n /// @notice Signals that the minimum weight has changed for a given asset\n event MinWeightChanged(ChainId chain, uint16 index, uint256 previous, uint256 current);\n\n /// @notice Defines risk-related configuration parameters for an asset.\n struct RiskParameters {\n /// @notice Percentage of asset value that can be counted as collateral (e.g., 90 = 90%).\n uint8 collateralFactor;\n\n /// @notice Percentage multiplier applied to liabilities for risk calculations (e.g., 90 = 90%).\n uint8 liabilityFactor;\n\n /// @notice Maximum allowable collateral amount for this asset. May be unenforced on-chain.\n uint256 maxCollateral;\n\n /// @notice Maximum total open interest allowed for derivatives positions.\n uint256 maxOpenInterest;\n\n /// @notice Maximum open interest allowed for spot positions.\n uint256 maxSpotOpenInterest;\n\n /// @notice Maximum allowed utilization ratio of available liquidity.\n uint256 maxUtilization;\n\n /// @notice If true, asset can only be used in isolated margin mode.\n bool isolatedOnly;\n\n /// @notice Utilization points where the interest rate curve slope changes, scaled in 1/100th of a basis point.\n uint256[] interestKinks;\n\n /// @notice Interest rates corresponding to `interestKinks`, scaled in 1/100th of a basis point.\n uint256[] kinkInterestRates;\n\n /// @notice USD-denominated utilization kink points, scaled in 1/100th of a basis point.\n uint256[] usdInterestKinks;\n\n /// @notice USD-denominated interest rates corresponding to `usdInterestKinks`, scaled in 1/100th of a basis point.\n uint256[] usdKinkInterestRates;\n\n /// @notice Multiplier applied to skew-based pricing adjustments, scaled in 1/100th of a basis point.\n uint256 skewModifier;\n\n /// @notice Skew threshold at which maximum skew adjustment applies, scaled in 1/100th of a basis point.\n uint256 skewCliff;\n\n /// @notice Base funding rate applied regardless of skew direction, scaled in 1/100th of a basis point.\n int256 baseFundingRate;\n\n /// @notice Maximum allowed premium adjustment, scaled in 1/100th of a basis point.\n uint256 premiumClamp;\n\n /// @notice Maximum premium impact applied during initial margin calculation, scaled in 1/100th of a basis point.\n uint256[] initialMarginClamps;\n\n /// @notice Multipliers applied to position size when calculating initial margin, scaled in 1/100th of a basis point.\n uint256[] initialMarginFactors;\n\n /// @notice Maximum absolute funding rate allowed, scaled in 1/100th of a basis point.\n uint256 maxFundingRate;\n\n /// @notice Maximum interest rate applied at full utilization, scaled in 1/100th of a basis point.\n uint256 maxUtilizationRate;\n\n /// @notice Additional safety buffer multiplier applied to risk calculations, scaled in 1/100th of a basis point.\n uint256 bufferMultiple;\n }\n\n struct PendingRiskParameters {\n RiskParameters parameters;\n uint256 validAfter;\n }\n\n /**\n * @notice Struct for managing a list of registered assets.\n * @dev Assets are stored by index and can span multiple chains.\n */\n struct AssetRegistry {\n uint256 count; // Total number of assets.\n mapping(uint16 => Asset) registry; // Mapping from index to asset struct.\n }\n\n /**\n * @notice Struct for identifying a chain.\n */\n struct ChainId {\n // The routing ID e.g. 0=EVM style chains.\n uint64 routingId;\n\n // e.g. EVM chainId.\n uint64 vmId;\n }\n\n /**\n * @notice Struct representing an asset across multiple chains.\n */\n struct Asset {\n mapping(uint64 => mapping(uint64 => AssetData)) data; // Routing ID => Chain ID => AssetData.\n ChainId[] chains; // List of all known chain IDs for this asset.\n }\n\n /**\n * @notice Chain-specific metadata for an asset.\n * @dev Uses bytes32 for `assetAddress` to support non-EVM chains like Solana.\n */\n struct AssetData {\n uint16 index;\n bytes32 assetAddress;\n ChainId chainId;\n uint256 maxDeposits; // Cap on deposits (collateral cap).\n uint256 max1hrDeposits; // Cap on fungible deposits over one hour\n uint256 minWeight; // Raw weight value (not percentage)\n }\n\n /// @notice Reverts if caller is not the admin.\n error NotAdmin();\n\n /// @notice Reverts if there is are no risk parameters queued for the specified asset\n error NoPendingRiskParameters(uint16 asset);\n\n /// @notice Reverts if the pending risk parameters are not yet eligible for application\n error TooSoon(uint16 asset, uint256 eligibleAt);\n\n /// @notice Reverts if caller is not the risk manager multisig.\n error NotRiskManager();\n\n /// @notice Reverts if the asset index is out of bounds.\n error IndexOutOfBounds();\n\n /// @notice Reverts if the collateral factor (CF) specified as part of risk parameters is greater than one\n error InvalidCollateralFactor();\n\n /// @notice Reverts if the liability factor (LF) specified as part of risk parameters is greater than one\n error InvalidLiabilityFactor();\n\n /// @notice Reverts if the utilization cap specified as part of risk parameters is greater than one\n error InvalidUtilizationCap();\n\n /// @notice Reverts if the funding rate cap specified as part of risk parameters is greater than ~1000% APR\n error InvalidMaxFundingRate();\n\n /// @notice Reverts if the utilization rate cap specified as part of risk parameters is greater than ~1000% APR\n error InvalidMaxUtilizationRate();\n\n /// @notice Reverts if the buffer multiple value is less than 1% or greater than 2%.\n error InvalidBufferMultiple();\n\n /// @notice Reverts if the interest kinks specified as part of risk parameters are not increasing from 0 to 1\n error InvalidInterestKinks();\n\n /// @notice Reverts if the interest rates specified as part of risk parameters are not increasing\n error InvalidRateInterestKinks();\n\n /// @notice Reverts if the USD-denominated interest kinks specified as part of risk parameters are not increasing from 0 to 1\n error InvalidUSDInterestKinks();\n\n /// @notice Reverts if the USD-denominated interest rates specified as part of risk parameters are not increasing\n error InvalidUSDRateInterestKinks();\n\n /// @notice Reverts if the size of the initial margin clamps does not match the size of the initial margin factors (specified as part of risk parameters)\n error InvalidInitialMarginsConfiguration();\n\n /// @notice Reverts if the initial margin clamps specified as part of risk parameters are not increasing or are above 100\n error InvalidInitialMarginsClamps();\n\n /// @notice Reverts if the initial margin clamps specified as part of risk parameters are not decreasing or are above 100\n error InvalidInitialMarginsFactors();\n\n /// @notice Reverts if adding a chain to an asset that already exists.\n error ChainAlreadyExists();\n\n /// @notice Reverts if an address is zero.\n error ZeroAddress();\n\n /// @notice Reverts if the risk manager is not set.\n error RiskManagerNotSet();\n\n /**\n * @notice Contract constructor.\n * @param _admin The admin controller of the vault.\n * @dev Sets the deployer as the initial admin.\n */\n constructor(address _admin) {\n admin = _admin;\n }\n\n /**\n * @notice Updates the risk manager multisig address.\n * @param multisig The new address to set.\n * @dev Reverts with `NotAdmin`; Only the admin can set a risk manager.\n */\n function setRiskManagerMultisig(address multisig) external {\n if (msg.sender != admin) revert NotAdmin();\n riskManagerMultisig = multisig;\n }\n\n /**\n * @notice Updates the admin address.\n * @param newAdmin The new admin address.\n * @dev Reverts with `NotAdmin`; Only the admin can set a new admin.\n * @dev The new administrator address is allowed to be the null address.\n * Setting the administrator to this address disables administration\n * of the registry contract.\n */\n function setAdmin(address newAdmin) external {\n if (msg.sender != admin) revert NotAdmin();\n if (newAdmin == address(0) && riskManagerMultisig == address(0)) {\n revert RiskManagerNotSet();\n }\n admin = newAdmin;\n }\n\n /**\n * @notice Sets or updates asset data for a specific asset index and chain.\n * @dev Automatically adds new assets or chain instances if not already present.\n * @param data The chain-specific asset data.\n * @dev Reverts with `NotRiskManager`; Only the risk manager can set asset data.\n */\n function setAssetData(AssetData memory data) external {\n if (msg.sender != riskManagerMultisig) revert NotRiskManager();\n if (data.index > assets.count) revert IndexOutOfBounds();\n\n // Prevent registering asset with zero-address. Zero-address means that asset\n // has not yet been set on a chain, where is this case it has.\n if (data.assetAddress == bytes32(0)) revert ZeroAddress();\n\n Asset storage reg = assets.registry[data.index];\n\n uint64 routingId = data.chainId.routingId;\n uint64 vmId = data.chainId.vmId;\n\n // Cannot edit the chain or address when already set.\n if (reg.data[routingId][vmId].assetAddress != bytes32(0)) {\n revert ChainAlreadyExists();\n }\n\n bool isNewAsset = reg.chains.length == 0;\n reg.data[routingId][vmId] = data;\n reg.chains.push(data.chainId);\n\n if (isNewAsset) {\n assets.count += 1;\n }\n }\n\n function setMaxDeposits(ChainId calldata chainId, uint16 index, uint256 newMaxDeposit)\n external\n {\n if (msg.sender != riskManagerMultisig) revert NotRiskManager();\n require(index < assets.count, \"!asset\");\n\n uint64 routingId = chainId.routingId;\n uint64 vmId = chainId.vmId;\n\n uint256 oldMaxDeposit = assets.registry[index].data[routingId][vmId].maxDeposits;\n assets.registry[index].data[routingId][vmId].maxDeposits = newMaxDeposit;\n emit MaxDepositChanged(chainId, index, oldMaxDeposit, newMaxDeposit);\n }\n\n function setMax1HrDeposits(ChainId calldata chainId, uint16 index, uint256 newMaxDeposit)\n external\n {\n if (msg.sender != riskManagerMultisig) revert NotRiskManager();\n require(index < assets.count, \"!asset\");\n\n uint64 routingId = chainId.routingId;\n uint64 vmId = chainId.vmId;\n\n uint256 oldMaxDeposit = assets.registry[index].data[routingId][vmId].max1hrDeposits;\n assets.registry[index].data[routingId][vmId].max1hrDeposits = newMaxDeposit;\n emit Max1HrDepositChanged(chainId, index, oldMaxDeposit, newMaxDeposit);\n }\n\n function setMinWeight(ChainId calldata chain, uint16 index, uint256 newMinWeight) external {\n if (msg.sender != riskManagerMultisig) revert NotRiskManager();\n require(index < assets.count, \"!asset\");\n uint256 oldMinWeight = assets.registry[index].data[chain.routingId][chain.vmId].minWeight;\n assets.registry[index].data[chain.routingId][chain.vmId].minWeight = newMinWeight;\n emit MinWeightChanged(chain, index, oldMinWeight, newMinWeight);\n }\n\n /**\n * @notice Retrieves asset data for a specific asset and chain.\n * @param chainId the chain ID to query.\n * @param index The asset index to query.\n * @return The corresponding AssetData struct.\n */\n function getAssetData(ChainId calldata chainId, uint16 index)\n external\n view\n returns (AssetData memory)\n {\n return assets.registry[index].data[chainId.routingId][chainId.vmId];\n }\n\n /**\n * @notice Returns all registered asset data across all chains.\n * @return An array of AssetData structs.\n * @param start The start index (inclusive).\n * @param end The end index (not-inclusive).\n */\n function getAssets(uint16 start, uint16 end) external view returns (AssetData[] memory) {\n // First, compute the total flattened entries\n uint256 totalEntries = 0;\n for (uint16 i = 0; i < assets.count; i++) {\n totalEntries += assets.registry[i].chains.length;\n }\n\n // Return empty array if start >= totalEntries\n if (start >= totalEntries) {\n return new AssetData[](0);\n }\n\n if (end > totalEntries) {\n // casting to 'uint16' is safe because we won't ever that many assets.\n // forge-lint: disable-next-line(unsafe-typecast)\n end = uint16(totalEntries);\n }\n\n if (end < start) {\n return new AssetData[](0);\n }\n\n uint16 length = end - start;\n AssetData[] memory result = new AssetData[](length);\n\n uint256 r = 0;\n uint256 resIdx = 0;\n\n for (uint16 i = 0; i < assets.count && resIdx < length; ++i) {\n Asset storage asset = assets.registry[i];\n uint256 chainsLen = asset.chains.length;\n\n for (uint256 c = 0; c < chainsLen && resIdx < length; ++c) {\n if (r >= start && r < end) {\n ChainId storage chain = asset.chains[c];\n result[resIdx++] = asset.data[chain.routingId][chain.vmId];\n }\n\n ++r;\n }\n }\n\n return result;\n }\n\n /**\n * @notice Returns the asset index for a given chain and address.\n * @param chainId The chain ID to search.\n * @param assetAddress The asset address (as bytes32).\n * @return The index of the asset, or `type(uint32).max` if not found.\n */\n function getAssetIndex(ChainId calldata chainId, bytes32 assetAddress)\n external\n view\n returns (uint32)\n {\n uint64 routingId = chainId.routingId;\n uint64 vmId = chainId.vmId;\n\n for (uint16 i = 0; i < assets.count; i++) {\n if (assetAddress == assets.registry[i].data[routingId][vmId].assetAddress) {\n return i;\n }\n }\n return type(uint32).max;\n }\n\n /**\n * @notice Sets pending risk parameters for a specific asset index.\n * @param index The asset index.\n * @param parameters The risk parameters to set\n * @dev Reverts with `NotRiskManager`; Only the risk manager can set risk parameters.\n * @dev Reverts with `\"!asset\"` if index >= assets.count.\n */\n function setPendingRiskParameters(uint16 index, RiskParameters memory parameters) external {\n if (msg.sender != riskManagerMultisig) revert NotRiskManager();\n require(index < assets.count, \"!asset\");\n validateRiskParameters(parameters);\n PendingRiskParameters memory pendingParams = PendingRiskParameters({\n parameters: parameters, validAfter: block.timestamp + riskParameterChangeDelaySeconds\n });\n pendingRiskParameters[index] = pendingParams;\n }\n\n /**\n * @notice Applies the pending risk parameters for the specified asset if they exist.\n * @param index The asset index.\n * @dev Reverts with `\"!asset\"` if index >= assets.count.\n * @dev Reverts with `NoPendingRiskParameters` if there are no pending risk parameters for the specified asset\n * @dev Reverts with `TooSoon` if the pending risk parameters are not yet eligible\n */\n function applyPendingRiskParameters(uint16 index) external {\n require(index < assets.count, \"!asset\");\n PendingRiskParameters memory pendingParams = pendingRiskParameters[index];\n if (pendingParams.validAfter == 0) revert NoPendingRiskParameters(index);\n if (pendingParams.validAfter >= block.timestamp) {\n revert TooSoon(index, pendingParams.validAfter);\n }\n RiskParameters memory params = pendingParams.parameters;\n validateRiskParameters(params);\n riskParameters[index] = params;\n delete pendingRiskParameters[index];\n }\n\n function validateRiskParameters(RiskParameters memory params) public pure {\n if (params.collateralFactor > 1e2) revert InvalidCollateralFactor();\n if (params.liabilityFactor > 1e2) revert InvalidLiabilityFactor();\n if (params.maxUtilization > 1e18) revert InvalidUtilizationCap();\n if (params.maxFundingRate > 1142) revert InvalidMaxFundingRate();\n if (params.maxUtilizationRate > 1142) revert InvalidMaxUtilizationRate();\n\n uint256 bufferMultiple = params.bufferMultiple;\n if (bufferMultiple < 1e6 || bufferMultiple > 2e6) revert InvalidBufferMultiple();\n\n if (!validateStartAtZeroIsAlwaysBelowOneAndIncreases(params.interestKinks)) {\n revert InvalidInterestKinks();\n }\n if (!validateLastIsOne(params.interestKinks)) revert InvalidInterestKinks();\n if (!validateStartAtZeroIsAlwaysBelowOneAndIncreases(params.usdInterestKinks)) {\n revert InvalidUSDInterestKinks();\n }\n if (!validateLastIsOne(params.usdInterestKinks)) revert InvalidUSDInterestKinks();\n\n if (!validateIncreases(params.kinkInterestRates)) {\n revert InvalidRateInterestKinks();\n }\n if (!validateIncreases(params.usdKinkInterestRates)) {\n revert InvalidUSDRateInterestKinks();\n }\n\n if (params.initialMarginClamps.length != params.initialMarginFactors.length) {\n revert InvalidInitialMarginsConfiguration();\n }\n if (!validateStartAtZeroIsAlwaysBelowOneAndIncreases(params.initialMarginClamps)) {\n revert InvalidInitialMarginsClamps();\n }\n if (!validateIMFactors(params.initialMarginFactors)) revert InvalidInitialMarginsFactors();\n }\n\n /**\n * @notice Last point should be (1_000_000)\n */\n function validateLastIsOne(uint256[] memory xs) internal pure returns (bool) {\n uint256 len = xs.length;\n return len != 0 && xs[len - 1] == 1_000_000;\n }\n\n /**\n * @notice Validate that a series of values is increasing\n */\n function validateIncreases(uint256[] memory xs) internal pure returns (bool) {\n uint256 len = xs.length;\n uint256 prev = 0;\n\n for (uint256 i; i < len; ++i) {\n uint256 cur = xs[i];\n if (cur < prev) return false;\n prev = cur;\n }\n\n return true;\n }\n\n /**\n * @notice IM clamps must always increase and be <= 1 (1_000_000), and first point must be 0\n */\n function validateStartAtZeroIsAlwaysBelowOneAndIncreases(uint256[] memory xs)\n internal\n pure\n returns (bool)\n {\n uint256 len = xs.length;\n uint256 prev = 0;\n\n if (len == 0 || xs[0] != 0) {\n return false;\n }\n\n for (uint256 i; i < len; ++i) {\n uint256 cur = xs[i];\n if (cur > 1_000_000) return false;\n if (cur < prev) return false;\n prev = cur;\n }\n\n return true;\n }\n\n /**\n * @notice IM factors must always decreases and be < 1 (1_000_000)\n */\n function validateIMFactors(uint256[] memory xs) internal pure returns (bool) {\n uint256 len = xs.length;\n uint256 prev = 999_999;\n\n for (uint256 i; i < len; ++i) {\n uint256 cur = xs[i];\n if (cur > prev) return false;\n prev = cur;\n }\n\n return true;\n }\n\n function sumIsOne(uint256[] memory xs) internal pure returns (bool) {\n uint256 len = xs.length;\n uint256 sum;\n\n for (uint256 i; i < len; ++i) {\n sum += xs[i];\n if (sum > 1e6) return false;\n }\n\n return sum == 1e6;\n }\n\n /**\n * @notice Returns the full list of risk parameters for all registered assets.\n * @return An array of RiskParameters.\n * @param start The start index (inclusive).\n * @param end The end index (not inclusive).\n */\n function getRiskParameters(uint16 start, uint16 end)\n external\n view\n returns (RiskParameters[] memory)\n {\n uint16 count = uint16(assets.count);\n\n if (start >= count) {\n return new RiskParameters[](0);\n }\n\n if (end > count) {\n end = count;\n }\n\n if (end < start) {\n return new RiskParameters[](0);\n }\n\n uint256 length = end - start;\n RiskParameters[] memory result = new RiskParameters[](length);\n\n for (uint16 i = 0; i < length; ++i) {\n result[i] = riskParameters[start + i];\n }\n\n return result;\n }\n\n function setFeeAccount(bytes32 account) external {\n if (msg.sender != riskManagerMultisig) revert NotRiskManager();\n feeAccount = account;\n }\n}\n","urls":[]},"src/interfaces/IAdminUpdateStrategy.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IAdminUpdateStrategy {\n function setAdministrators(\n address vault,\n address[] calldata newAdministrators,\n uint256 newWithdrawalQuorum\n ) external payable;\n}\n","urls":[]},"src/interfaces/IAtomicSettlementCallback.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IAtomicSettlementCallback {\n /// @notice Computes the minimum expected quantity of `token` that will be\n /// received by the deposit vault upon execution of an atomic\n /// settlement request\n function onAtomicSettlement(address token, uint256 amount, bytes calldata data)\n external\n returns (uint256);\n}\n","urls":[]},"src/interfaces/IAutomataDcapAttestation.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/// @notice Interface for Automata's DCAP Attestation Verifier (V3)\n/// @dev Bindings for the 'AutomataDcapAttestation' contract.\n/// Compatible with Automata V3 ZK Coprocessor logic.\ninterface IAutomataDcapAttestation {\n // Enum definition from Automata's library\n enum ZkCoProcessorType {\n RiscZero,\n Succinct // SP1\n }\n\n /// @notice Verifies a SNARK proof (Groth16) for a TEE Quote.\n /// @param output The Public Values (Journal) - effectively the Quote Body.\n /// @param zkvm The type of ZKVM used.\n /// @param proofBytes The actual (Groth16) proof.\n /// @return success True if valid.\n /// @return errorData Error message if failed, or empty if success.\n function verifyAndAttestWithZKProof(\n bytes calldata output,\n ZkCoProcessorType zkvm,\n bytes calldata proofBytes\n ) external returns (bool success, bytes memory errorData);\n}\n","urls":[]},"src/interfaces/ICheckpointer.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface ICheckpointer {\n struct Checkpoint {\n uint256 nonce;\n uint8[] stateRoot;\n string[] approvedWithdrawals;\n }\n\n error AlreadySet();\n error InvalidSignature();\n error NotAdmin();\n error NotCouncilMultisig();\n\n event Withdrawals(string[] approvedWithdrawals);\n\n function CHECKPOINT_TYPEHASH() external view returns (bytes32);\n function admin() external view returns (address);\n function checkpoint(\n bytes memory sharedSignature,\n bytes memory leaderSignature,\n Checkpoint memory _checkpoint\n ) external;\n function councilMultisig() external view returns (address);\n function leader() external view returns (address);\n function setAdmin(address newAdmin) external;\n function setDomainSeparator(bytes32 domainSeparator) external;\n function setInitialCouncilMultisig(address newCouncilMultisig) external;\n function setLeader(address newLeader) external;\n function setNewCouncilMultisig(address newCouncilMultisig) external;\n function stateRoot(uint256) external view returns (uint8);\n function stateRootNonce() external view returns (uint256);\n}\n","urls":[]},"src/interfaces/ICredentialManager.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface CredentialManager {\n struct ChainConfig {\n uint64 blockTimeMs;\n uint8 defaultConfirmations;\n uint8 depositIngestConfirmations;\n uint8 withdrawalIngestConfirmations;\n uint8 settlementIngestConfirmations;\n }\n\n struct MeasurementProfile {\n bool active;\n bytes32 mrtd;\n bytes32 rtmr0;\n bytes32 rtmr1;\n bytes32 rtmr2;\n bytes32 rtmr3;\n }\n\n struct Vault {\n uint8 routingId;\n uint256 vmId;\n bytes32 vaultAddress;\n ChainConfig config;\n }\n\n error AmbiguousState();\n error CannotCancel();\n error GatheringActive();\n error GatheringNotActive();\n error GatheringNotExpired();\n error InsufficientSignatures(uint256 provided, uint256 required);\n error InvalidDelay(uint256 delay);\n error InvalidEpoch(uint256 expected, uint256 actual);\n error InvalidProfileConfig();\n error InvalidProfileId();\n error InvalidQuorum(uint256 newQuorum, uint256 operatorCount);\n error InvalidQuoteLength();\n error InvalidReportData();\n error InvalidVaultAddr();\n error InvalidVerifier();\n error MeasurementMismatch(bytes32 expected, bytes32 actual, string field);\n error NoCandidate();\n error NoStrategy();\n error NotOperator(address signer);\n error ProfileInactive(uint256 profileId);\n error ProposedEpochTooLow(uint256 current, uint256 proposed);\n error SignersNotSortedOrUnique();\n error StrategyAlreadyExists();\n error TimelockAlreadyCanceled(bytes32 opId);\n error TimelockAlreadyExecuted(bytes32 opId);\n error TimelockNotReady(bytes32 opId, uint256 readyAt, uint256 nowTs);\n error TimelockUnknown(bytes32 opId);\n error VaultNotFound(uint256 routingId, uint256 vmId);\n error ZeroAddress();\n\n event AdminUpdateStrategyRegistered(\n uint256 indexed routingId, uint256 indexed vmId, address strategy\n );\n event AttestedKeyRegistered(address indexed operator, bytes32 indexed newAttestedKey);\n event AutomataVerifierUpdated(address indexed oldVerifier, address indexed newVerifier);\n event DepositVaultAdministratorsUpdated(\n uint256 indexed routingId,\n uint256 indexed vmId,\n address[] newAdministrators,\n uint256 newWithdrawalQuorum\n );\n event DepositVaultAdministratorsUpdated(\n uint256 indexed chainId, address[] newAdministrators, uint256 newWithdrawalQuorum\n );\n event EpochIncremented(uint256 newEpoch, bytes32 newCheckpointHash);\n event LeaderUpdated(address indexed newLeader, bytes32 indexed newAttestedKey);\n event MeasurementProfileUpdated(uint256 indexed profileId, bool active);\n event MeasurementsUpdated(bytes32 newMrtd, bytes32 newRtmr0);\n event OperationCanceled(bytes32 indexed opId, bytes32 indexed opType);\n event OperationExecuted(bytes32 indexed opId, bytes32 indexed opType);\n event OperationScheduled(bytes32 indexed opId, bytes32 indexed opType, uint256 eta);\n event OperatorAdded(address indexed operator);\n event QuorumThresholdUpdated(uint256 oldThreshold, uint256 newThreshold);\n event RegistryUpdated(address indexed oldRegistry, address indexed newRegistry);\n event RestartAmbiguityDetected(uint256 epoch, bytes32 hash1, bytes32 hash2);\n event RestartCandidateSubmitted(address indexed leader, uint256 epoch, bytes32 checkpointHash);\n event RestartExecuted(address indexed newLeader, uint256 indexed epoch);\n event RestartGatheringStarted(uint256 deadline);\n event RiskManagerUpdated(address indexed oldRiskManager, address indexed newRiskManager);\n event TimelockDelayUpdated(bytes32 indexed targetOpType, uint256 oldDelay, uint256 newDelay);\n event VaultAdded(\n uint256 indexed routingId, uint256 indexed vmId, bytes32 vaultAddr, ChainConfig config\n );\n\n receive() external payable;\n\n function GATHERING_DURATION() external view returns (uint256);\n function OP_ADD_VAULT() external view returns (bytes32);\n function OP_APPOINT_LEADER() external view returns (bytes32);\n function OP_CANCEL_TIMELOCK() external view returns (bytes32);\n function OP_MANAGE_PROFILE() external view returns (bytes32);\n function OP_REGISTER_STRATEGY() external view returns (bytes32);\n function OP_RESTART() external view returns (bytes32);\n function OP_SET_AUTOMATA_VERIFIER() external view returns (bytes32);\n function OP_SET_DELAY() external view returns (bytes32);\n function OP_SET_MEASUREMENTS() external view returns (bytes32);\n function OP_SET_QUORUM() external view returns (bytes32);\n function OP_SET_REGISTRY() external view returns (bytes32);\n function OP_SET_RISK_MANAGER() external view returns (bytes32);\n function OP_SET_VAULT_ADMINS() external view returns (bytes32);\n function OP_WITHDRAW() external view returns (bytes32);\n function addVault(\n uint8 routingId,\n uint256 vmId,\n bytes32 vaultAddr,\n ChainConfig memory config,\n address[] memory signers,\n bytes[] memory signatures\n ) external;\n function admin() external view returns (address);\n function adminUpdateStrategies(uint256, uint256) external view returns (address);\n function appointLeader(address newLeader, address[] memory signers, bytes[] memory signatures)\n external;\n function automataVerifier() external view returns (address);\n function bestCandidate()\n external\n view\n returns (address leader, uint256 epoch, bytes32 checkpointHash, bool exists);\n function cancelTimelock(bytes32 opId, address[] memory signers, bytes[] memory signatures)\n external;\n function domainSeparator() external view returns (bytes32);\n function epoch() external view returns (uint256);\n function executeManageProfile(uint256 profileId, MeasurementProfile memory profile) external;\n function executeRegistryContract(address newRegistry) external;\n function executeRiskManager(address newRiskManager) external;\n function executeUpdateAutomataVerifier(address newVerifier) external;\n function getCouncilConfig()\n external\n view\n returns (address[] memory members, uint256 k, uint256 n);\n function getLeader() external view returns (address operator, bytes32 attestedKey);\n function getVaults(uint16 start, uint16 end) external view returns (Vault[] memory);\n function governanceNonce() external view returns (uint256);\n function initiateRestart() external;\n function isOperator(address) external view returns (bool);\n function isRestartAmbiguous() external view returns (bool);\n function latestCheckpointHash() external view returns (bytes32);\n function leader() external view returns (address);\n function measurementProfiles(uint256)\n external\n view\n returns (\n bool active,\n bytes32 mrtd,\n bytes32 rtmr0,\n bytes32 rtmr1,\n bytes32 rtmr2,\n bytes32 rtmr3\n );\n function nextProfileId() external view returns (uint256);\n function operatorToAttestedKey(address) external view returns (bytes32);\n function operators(uint256) external view returns (address);\n function quorumThreshold() external view returns (uint256);\n function registerAdminUpdateStrategy(\n uint8 routingId,\n uint256 vmId,\n address strategy,\n address[] memory signers,\n bytes[] memory signatures\n ) external;\n function registerAttestedKey(bytes32 newAttestedKey) external;\n function registryContract() external view returns (address);\n function resolveRestart() external;\n function restartGatheringDeadline() external view returns (uint256);\n function riskManager() external view returns (address);\n function scheduleManageProfile(\n uint256 profileId,\n MeasurementProfile memory profile,\n address[] memory signers,\n bytes[] memory signatures\n ) external returns (bytes32 opId);\n function scheduleRegistryContract(\n address newRegistry,\n address[] memory signers,\n bytes[] memory signatures\n ) external returns (bytes32 opId);\n function scheduleRiskManager(\n address newRiskManager,\n address[] memory signers,\n bytes[] memory signatures\n ) external returns (bytes32 opId);\n function scheduleUpdateAutomataVerifier(\n address newVerifier,\n address[] memory signers,\n bytes[] memory signatures\n ) external returns (bytes32 opId);\n function setDepositVaultAdministrators(\n uint256 routingId,\n uint256 vmId,\n address[] memory newAdministrators,\n uint256 newWithdrawalQuorum,\n address[] memory signers,\n bytes[] memory signatures\n ) external payable;\n function submitRestartProof(\n uint256 profileId,\n bytes memory tdxReportBody,\n bytes memory zkProof,\n address newLeader,\n bytes32 checkpointHash\n ) external;\n function timelockDelayFor(bytes32) external view returns (uint256);\n function timelockOps(bytes32)\n external\n view\n returns (uint64 eta, bool executed, bool canceled, bytes32 opType);\n function updateQuorumThreshold(\n uint256 newThreshold,\n address[] memory signers,\n bytes[] memory signatures\n ) external;\n function vaults(uint256)\n external\n view\n returns (uint8 routingId, uint256 vmId, bytes32 vaultAddress, ChainConfig memory config);\n function verifyMeasurements(\n uint256 profileId,\n bytes32 checkMrtd,\n bytes32 checkRtmr0,\n bytes32 checkRtmr1,\n bytes32 checkRtmr2,\n bytes32 checkRtmr3\n ) external view;\n function withdraw(address account, address[] memory signers, bytes[] memory signatures) external;\n}\n","urls":[]},"src/interfaces/IDepositVault.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IDepositVault {\n struct Settlement {\n address tokenOut;\n uint256 amountOut;\n address tokenIn;\n uint256 amountIn;\n uint256 nonce;\n }\n\n struct SignedSettlement {\n Settlement settlement;\n bytes signature;\n }\n\n struct Withdrawal {\n address tokenAddress;\n uint256 amount;\n uint256 nonce;\n }\n\n error EmptyOrders();\n error Expired();\n error InsufficientAdministrators(uint256 actual, uint256 required);\n error InvalidNonce(uint256 expected, uint256 given);\n error InvalidSignature();\n error NotAdmin();\n error NotCredentialManager();\n error NotExecutor();\n error NotOwner();\n error TooSoon();\n error ZeroAddress();\n error ZeroWithdrawalQuorum();\n error MissedQuorum(uint256 provided, uint256 required);\n\n event AdminAdded(address newAdmin, uint256 numAdminsAfter);\n event AdministratorSetReset();\n event CredentialManagerChanged(address oldCredentialManager, address newCredentialManager);\n event Deposited(\n bytes32 indexed user, uint256 indexed nonce, address tokenAddress, uint256 amount\n );\n event Settled(\n bytes32 indexed user,\n uint256 indexed nonce,\n address tokenOut,\n uint256 amountOut,\n address tokenIn,\n uint256 amountIn\n );\n event WithdrawalQuorumChanged(uint256 previous, uint256 current);\n event Withdrew(\n bytes32 indexed user, uint256 indexed nonce, address tokenAddress, uint256 amount\n );\n\n function ORDER_TYPEHASH() external view returns (bytes32);\n function addSettlerExecutor(bytes32 settler, address executor) external;\n function administrators(uint256) external view returns (address);\n function approvedSettlers(uint256) external view returns (bytes32);\n function canDeposit(address) external view returns (bool);\n function credentialManager() external view returns (address);\n function credentialManagerChangeDelayBlocks() external view returns (uint256);\n function deposit(bytes32 user, address tokenAddress, uint256 amount) external;\n function depositCounts(bytes32) external view returns (uint256);\n function executeAtomicSettlement(\n Settlement memory order,\n bytes32 user,\n uint256 validUntil,\n bytes memory data,\n bytes memory signature\n ) external;\n function getApprovedSettlers() external view returns (bytes32[] memory);\n function isAdministrator(address account) external view returns (bool);\n function lastSignatureUse() external view returns (uint256);\n function owner() external view returns (address);\n function ownerWithdrawToken(address token, address to, uint256 amount) external;\n function pendingSettlements(bytes32, uint256)\n external\n view\n returns (Settlement memory settlement, address target);\n function pullBatchSettlement(\n SignedSettlement[] memory orders,\n bytes32 user,\n address target,\n uint256 validUntil\n ) external;\n function pushBatchSettlements(bytes32 user) external;\n function removeSettler(bytes32 settler) external;\n function setAdministrators(address[] memory newAdministrators, uint256 newWithdrawalQuorum)\n external;\n function setCredentialManager(address newCredentialManager) external;\n function setDepositorStatus(address depositor, bool allowed) external;\n function setDomainSeparator(bytes32 domainSeparator) external;\n function setOwner(address newOwner) external;\n function settlementCaps(address) external view returns (uint256);\n function settlementCounts(bytes32) external view returns (uint256);\n function withdraw(\n Withdrawal memory withdrawal,\n bytes32 user,\n address target,\n uint256 validUntil,\n bytes32 epochHash,\n bytes memory signature\n ) external;\n function withdrawalCounts(bytes32) external view returns (uint256);\n function withdrawalQuorum() external view returns (uint256);\n}\n","urls":[]},"src/interfaces/IRegistry.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IRegistry {\n struct AssetData {\n uint16 index;\n bytes32 assetAddress;\n uint64 chainId;\n uint256 maxDeposits;\n uint256 max1hrDeposits;\n uint256 minWeight;\n }\n\n struct RiskParameters {\n uint8 collateralFactor;\n uint8 liabilityFactor;\n uint256 maxCollateral;\n uint256 maxOpenInterest;\n uint256 maxSpotOpenInterest;\n uint256 maxUtilization;\n bool isolatedOnly;\n uint256[] interestKinks;\n uint256[] kinkInterestRates;\n uint256[] usdInterestKinks;\n uint256[] usdKinkInterestRates;\n uint256 skewModifier;\n uint256 skewCliff;\n int256 baseFundingRate;\n uint256 premiumClamp;\n uint256[] initialMarginClamps;\n uint256[] initialMarginFactors;\n uint256 maxFundingRate;\n uint256 maxUtilizationRate;\n uint256 bufferMultiple;\n }\n\n error ChainAlreadyExists();\n error IndexOutOfBounds();\n error InvalidBufferMultiple();\n error InvalidCollateralFactor();\n error InvalidInitialMarginsClamps();\n error InvalidInitialMarginsConfiguration();\n error InvalidInitialMarginsFactors();\n error InvalidInterestKinks();\n error InvalidLiabilityFactor();\n error InvalidMaxFundingRate();\n error InvalidMaxUtilizationRate();\n error InvalidRateInterestKinks();\n error InvalidUSDInterestKinks();\n error InvalidUSDRateInterestKinks();\n error InvalidUtilizationCap();\n error NoPendingRiskParameters(uint16 asset);\n error NotAdmin();\n error NotRiskManager();\n error RiskManagerNotSet();\n error TooSoon(uint16 asset, uint256 eligibleAt);\n error ZeroAddress();\n\n event Max1HrDepositChanged(uint64 chain, uint16 index, uint256 previous, uint256 current);\n event MaxDepositChanged(uint64 chain, uint16 index, uint256 previous, uint256 current);\n event MinWeightChanged(uint64 chain, uint16 index, uint256 previous, uint256 current);\n\n function admin() external view returns (address);\n function applyPendingRiskParameters(uint16 index) external;\n function feeAccount() external view returns (bytes32);\n function getAssetData(uint64 chainId, uint16 index) external view returns (AssetData memory);\n function getAssetIndex(uint64 chainId, bytes32 assetAddress) external view returns (uint32);\n function getAssets(uint16 start, uint16 end) external view returns (AssetData[] memory);\n function getRiskParameters(uint16 start, uint16 end)\n external\n view\n returns (RiskParameters[] memory);\n function pendingRiskParameters(uint16)\n external\n view\n returns (RiskParameters memory parameters, uint256 validAfter);\n function riskManagerMultisig() external view returns (address);\n function riskParameterChangeDelaySeconds() external view returns (uint256);\n function riskParameters(uint16)\n external\n view\n returns (\n uint8 collateralFactor,\n uint8 liabilityFactor,\n uint256 maxCollateral,\n uint256 maxOpenInterest,\n uint256 maxSpotOpenInterest,\n uint256 maxUtilization,\n bool isolatedOnly,\n uint256 skewModifier,\n uint256 skewCliff,\n int256 baseFundingRate,\n uint256 premiumClamp,\n uint256 maxFundingRate,\n uint256 maxUtilizationRate,\n uint256 bufferMultiple\n );\n function setAdmin(address newAdmin) external;\n function setAssetData(AssetData memory data) external;\n function setFeeAccount(bytes32 account) external;\n function setMax1HrDeposits(uint16 chain, uint16 index, uint256 newMaxDeposit) external;\n function setMaxDeposits(uint16 chain, uint16 index, uint256 newMaxDeposit) external;\n function setMinWeight(uint16 chain, uint16 index, uint256 newMinWeight) external;\n function setPendingRiskParameters(uint16 index, RiskParameters memory parameters) external;\n function setRiskManagerMultisig(address multisig) external;\n function validateRiskParameters(RiskParameters memory params) external pure;\n}\n","urls":[]},"src/strategies/ArbitrumOneAdminUpdateStrategy.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {IInbox} from \"nitro-contracts/bridge/IInbox.sol\";\nimport {IDepositVault} from \"../interfaces/IDepositVault.sol\";\nimport {IAdminUpdateStrategy} from \"../interfaces/IAdminUpdateStrategy.sol\";\n\ncontract ArbitrumOneAdminUpdateStrategy is IAdminUpdateStrategy {\n address public constant INBOX = 0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f;\n\n uint256 constant MAX_SUBMISSION_COST = 0.02 ether;\n uint256 constant GAS_LIMIT = 3_000_000;\n uint256 constant MAX_FEE_PER_GAS = 5 gwei;\n\n /// @notice Reverts if not enough value was sent to the update method.\n error InsufficientMsgValue(uint256 actual, uint256 expected);\n\n /**\n * @notice Updates the administrator set and withdrawal quorum on a vault via a retryable ticket.\n * @dev This function forwards a cross-chain call to the target `vault` using Arbitrum's\n * retryable ticket mechanism. The credential manager must supply sufficient `msg.value` to cover\n * the maximum submission cost and gas fees for execution on the destination chain.\n *\n * @param vault The address of the vault contract whose administrators will be updated.\n * @param newAdministrators The complete list of administrator addresses to set on the vault.\n * @param newWithdrawalQuorum The new quorum required for withdrawals.\n *\n * @dev Reverts with {InsufficientMsgValue} if `msg.value` is less than\n * `MAX_SUBMISSION_COST + GAS_LIMIT * MAX_FEE_PER_GAS`.\n */\n function setAdministrators(\n address vault,\n address[] calldata newAdministrators,\n uint256 newWithdrawalQuorum\n ) external payable override {\n uint256 expectedValue =\n MAX_SUBMISSION_COST + GAS_LIMIT * MAX_FEE_PER_GAS;\n uint256 actualValue = msg.value;\n\n if (actualValue < expectedValue) {\n revert InsufficientMsgValue(actualValue, expectedValue);\n }\n\n bytes memory callData = abi.encodeWithSelector(\n IDepositVault.setAdministrators.selector, newAdministrators, newWithdrawalQuorum\n );\n\n IInbox inbox = IInbox(address(INBOX));\n inbox.createRetryableTicket{value: msg.value}(\n vault,\n 0,\n MAX_SUBMISSION_COST,\n msg.sender,\n msg.sender,\n GAS_LIMIT,\n MAX_FEE_PER_GAS,\n callData\n );\n }\n}\n","urls":[]},"src/strategies/IntraChainAdminUpdateStrategy.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {IAdminUpdateStrategy} from \"../interfaces/IAdminUpdateStrategy.sol\";\nimport {IDepositVault} from \"../interfaces/IDepositVault.sol\";\n\n/// Use this strategy when updating the vault on the same chain as the credential manager.\ncontract IntraChainAdminUpdateStrategy is IAdminUpdateStrategy {\n function setAdministrators(\n address vault,\n address[] calldata newAdministrators,\n uint256 newWithdrawalQuorum\n ) external payable {\n IDepositVault(vault).setAdministrators(newAdministrators, newWithdrawalQuorum);\n }\n}\n","urls":[]},"src/strategies/OPStackAdminUpdateStrategy.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {IDepositVault} from \"../interfaces/IDepositVault.sol\";\nimport {IAdminUpdateStrategy} from \"../interfaces/IAdminUpdateStrategy.sol\";\n\ninterface IL1CrossDomainMessenger {\n function sendMessage(address _target, bytes calldata _message, uint32 _minGasLimit)\n external\n payable;\n}\n\n/// @notice Admin update strategy for OP Stack chains (Optimism, Base, Unichain, etc)\ncontract OPStackAdminUpdateStrategy is IAdminUpdateStrategy {\n /// @notice L1 CrossDomainMessenger.\n address public immutable L1_CROSS_DOMAIN_MESSENGER;\n\n /// @notice Conservative gas limit for L2 execution.\n uint32 public constant L2_GAS_LIMIT = 3_000_000;\n\n /// @notice Reverts if messenger address is zero.\n error ZeroMessengerAddress();\n\n constructor(address l1CrossDomainMessenger) {\n if (l1CrossDomainMessenger == address(0)) revert ZeroMessengerAddress();\n L1_CROSS_DOMAIN_MESSENGER = l1CrossDomainMessenger;\n }\n\n /**\n * @notice Updates the administrator set and withdrawal quorum on an OP Stack L2 vault\n * @dev Sends a cross-domain message from L1 \u2192 L2 using the OP Stack messenger\n * @dev Forwards msg.value directly to the L1 messenger\n *\n * @param vault The L2 vault address\n * @param newAdministrators The full administrator set\n * @param newWithdrawalQuorum The withdrawal quorum\n */\n function setAdministrators(\n address vault,\n address[] calldata newAdministrators,\n uint256 newWithdrawalQuorum\n ) external payable override {\n bytes memory callData = abi.encodeWithSelector(\n IDepositVault.setAdministrators.selector, newAdministrators, newWithdrawalQuorum\n );\n\n IL1CrossDomainMessenger(L1_CROSS_DOMAIN_MESSENGER).sendMessage{value: msg.value}(\n vault, callData, L2_GAS_LIMIT\n );\n }\n}\n","urls":[]}}} \ No newline at end of file From 44ca0b801803eaca765e21ebe439dad34cb9b894 Mon Sep 17 00:00:00 2001 From: antazoey Date: Tue, 10 Feb 2026 16:43:45 -0600 Subject: [PATCH 02/16] fix: smarter deploy devs --- tplus/evm/contracts.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tplus/evm/contracts.py b/tplus/evm/contracts.py index edd63db..eec663c 100644 --- a/tplus/evm/contracts.py +++ b/tplus/evm/contracts.py @@ -10,6 +10,7 @@ from ape.managers.project import Project from ape.types.address import AddressType from ape.utils.basemodel import ManagerAccessMixin +from ape.utils.misc import ZERO_ADDRESS from eth_pydantic_types.hex.bytes import HexBytes, HexBytes32 from tplus.evm.abi import get_erc20_type @@ -215,7 +216,7 @@ def deploy(cls, *args, sender: AccountAPI, **kwargs) -> "TPlusContract": return cls(default_deployer=sender, chain_id=chain_id, address=instance.address, **kwargs) @classmethod - def deploy_dev(cls): + def deploy_dev(cls, **kwargs): owner = get_dev_default_owner() return cls.deploy(owner, sender=owner) @@ -478,7 +479,7 @@ def deploy(cls, *args, sender: AccountAPI, **kwargs) -> "DepositVault": return instance @classmethod - def deploy_dev(cls, sender: AccountAPI | None = None) -> TPlusContract: + def deploy_dev(cls, sender: AccountAPI | None = None, **kwargs) -> TPlusContract: """ Deploy and set up a development vault. """ @@ -519,6 +520,25 @@ class CredentialManager(TPlusContract): NAME = "CredentialManager" + @classmethod + def deploy_dev(cls, **kwargs) -> "ReceiptAPI": + owner = kwargs.get("owner") or get_dev_default_owner() + operators = kwargs.get("operators", [owner.address]) + threshold = kwargs.get("quorum_threshold") or len(operators) + registry_address = kwargs.get("registry") or ZERO_ADDRESS + measurements = kwargs.get("measurements") or [] + automata_verifier = kwargs.get("automata_verifier") or ZERO_ADDRESS + + return cls.deploy( + operators, + owner, + threshold, + registry_address, + measurements, + automata_verifier, + sender=owner, + ) + def add_vault(self, address: AddressType, chain_id: ChainID | None = None, **kwargs): if not isinstance(address, str): # Allow ENS or certain classes to work. From c552cd383f791b11fb80e018b5c89f717ab4bc0f Mon Sep 17 00:00:00 2001 From: antazoey Date: Tue, 10 Feb 2026 16:49:20 -0600 Subject: [PATCH 03/16] order --- tplus/evm/contracts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tplus/evm/contracts.py b/tplus/evm/contracts.py index eec663c..801e04d 100644 --- a/tplus/evm/contracts.py +++ b/tplus/evm/contracts.py @@ -531,8 +531,8 @@ def deploy_dev(cls, **kwargs) -> "ReceiptAPI": return cls.deploy( operators, - owner, threshold, + owner, registry_address, measurements, automata_verifier, From 88b423b1fc750da0030694b57c62bce83d644991 Mon Sep 17 00:00:00 2001 From: antazoey Date: Tue, 10 Feb 2026 17:03:17 -0600 Subject: [PATCH 04/16] fix deploy dev --- tplus/evm/contracts.py | 35 +++++++++++++++++++---------------- tplus/evm/managers/vault.py | 18 +++++++++--------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/tplus/evm/contracts.py b/tplus/evm/contracts.py index 801e04d..09be522 100644 --- a/tplus/evm/contracts.py +++ b/tplus/evm/contracts.py @@ -15,7 +15,6 @@ from tplus.evm.abi import get_erc20_type from tplus.evm.constants import LATEST_ARB_DEPOSIT_VAULT, REGISTRY_ADDRESS -from tplus.evm.eip712 import Domain from tplus.evm.exceptions import ContractNotExists from tplus.model.asset_identifier import ChainAddress from tplus.model.types import ChainID, UserPublicKey @@ -459,18 +458,11 @@ def execute_atomic_settlement( @classmethod def deploy(cls, *args, sender: AccountAPI, **kwargs) -> "DepositVault": - owner = args[0] if args else sender + args = list(args) + args[0] = args[0] if args else sender address = sender.get_deployment_address() - separator = ( - args[1] - if len(args) > 1 - else Domain( - cls.chain_manager.chain_id, - address, - ).separator - ) - instance = super().deploy(owner, separator, sender=sender, **kwargs) + instance = super().deploy(*args, sender=sender, **kwargs) if instance.address != address: # Shouldn't happen - but just in case, as this will cause hard to detect problems. @@ -483,19 +475,30 @@ def deploy_dev(cls, sender: AccountAPI | None = None, **kwargs) -> TPlusContract """ Deploy and set up a development vault. """ + credman = kwargs.get("credential_manager") or ZERO_ADDRESS sender = sender or cls.account_manager.test_accounts[0] - contract = cast(DepositVault, cls.deploy(sender=sender)) + contract = cast(DepositVault, cls.deploy(sender, credman, sender=sender)) # Set the owner as an admin who can approve settlements/withdrawals. # (we only do this in dev mode; irl the roles are different). - contract.set_admin_status(sender, True, sender) + credman_account = cls.account_manager[credman] + credman_account.balance += int(1e18) + contract.set_administrators([sender], credman_account) return contract - def set_admin_status( - self, admin: "AddressType", status: bool, vault_owner: AccountAPI + def set_administrators( + self, + administrators: list["AddressType"], + vault_owner: AccountAPI, + withdrawal_quorum: int | None = None, ) -> "ReceiptAPI": - return self.contract.setAdmin(admin, status, sender=vault_owner) + if withdrawal_quorum is None: + withdrawal_quorum = len(administrators) + + return self.contract.setAdministrators( + administrators, withdrawal_quorum, sender=vault_owner + ) def set_domain_separator(self, domain_separator: bytes, *, sender: AccountAPI) -> "ReceiptAPI": return self.contract.setDomainSeparator(domain_separator, sender=sender) diff --git a/tplus/evm/managers/vault.py b/tplus/evm/managers/vault.py index ca6d001..48b6636 100644 --- a/tplus/evm/managers/vault.py +++ b/tplus/evm/managers/vault.py @@ -47,10 +47,10 @@ def set_domain_separator(self, domain_separator: bytes, **tx_kwargs) -> "Receipt return self.vault.set_domain_separator(domain_separator, **tx_kwargs) - async def register_admin( + async def set_administrators( self, - admin_key: str | None = None, - verify: bool = False, + admin_keys: list[str] | None = None, + withdrawal_quorum: int | None = None, **tx_kwargs, ) -> "ReceiptAPI": """ @@ -59,18 +59,18 @@ async def register_admin( """ tx_kwargs.setdefault("sender", self.owner) - if admin_key is None: + if admin_keys is None: if self.ce is None: raise ValueError("Either admin_key or self.ce must be specified") - admin_key = await self.ce.admin.get_verifying_key() + admin_keys = [await self.ce.admin.get_verifying_key()] - address = public_key_to_address(admin_key) + addresses = [public_key_to_address(k) for k in admin_keys] - tx = self.vault.setAdmin(address, True, **tx_kwargs) - if verify: - self.vault.isAdmin(address) + if withdrawal_quorum is None: + withdrawal_quorum = len(addresses) + tx = self.vault.setAdministrators(addresses, withdrawal_quorum, **tx_kwargs) return tx async def register_settler( From d6e51854f7460f970e86b45c311841477ab87642 Mon Sep 17 00:00:00 2001 From: antazoey Date: Wed, 11 Feb 2026 09:08:19 -0600 Subject: [PATCH 05/16] fix more stuff --- tests/evm/test_contract.py | 19 +++- tplus/evm/constants.py | 2 +- tplus/evm/contracts.py | 48 +++++++-- tplus/evm/managers/credential_manager.py | 129 +++++++++++++++++++++-- tplus/model/asset_identifier.py | 2 +- tplus/model/config.py | 70 ++++++++++++ 6 files changed, 245 insertions(+), 25 deletions(-) create mode 100644 tplus/model/config.py diff --git a/tests/evm/test_contract.py b/tests/evm/test_contract.py index 19b07e2..ae4125a 100644 --- a/tests/evm/test_contract.py +++ b/tests/evm/test_contract.py @@ -39,7 +39,8 @@ def test_address_from_lookup(self): class TestDepositVault: def test_deploy(self, accounts): owner = accounts[0] - instance = DepositVault.deploy(sender=owner) + credential_manager = accounts[2] + instance = DepositVault.deploy(owner, credential_manager, sender=owner) # It should know its address. assert instance.address assert instance.owner() == owner.address @@ -48,7 +49,8 @@ def test_deploy_different_owner(self, accounts): owner = accounts[0] sender = accounts[1] deployer_nonce_before = sender.nonce - instance = DepositVault.deploy(owner, sender=sender) + credential_manager = accounts[2] + instance = DepositVault.deploy(owner, credential_manager, sender=sender) deployer_nonce_after = sender.nonce # It should know its address. assert instance.address @@ -62,17 +64,26 @@ def test_from_chain_address(self): def test_domain_separator(self, accounts, chain): owner = accounts[0] + credential_manager = accounts[2] # Sets domain separator automatically. - instance = DepositVault.deploy(sender=owner) - + instance = DepositVault.deploy(owner, credential_manager, sender=owner) expected = Domain(chain.chain_id, instance.address).separator + instance.set_domain_separator(expected, sender=owner) # Reads using `eth_getStorageAt()` RPC. actual = instance.domain_separator assert actual == expected + def test_chain_address(self, accounts): + owner = accounts[0] + instance = DepositVault.deploy(owner, owner, sender=owner) + actual = instance.chain_address + assert actual.evm_address == instance.address + assert actual.chain_id.routing_id == 0 + assert actual.chain_id.vm_id == accounts.chain_manager.chain_id + @pytest.mark.parametrize("error", ("TransferFromFailed()", "TransferFailed()")) def test_decode_erc20_error(error): diff --git a/tplus/evm/constants.py b/tplus/evm/constants.py index fac5bb7..2f908ed 100644 --- a/tplus/evm/constants.py +++ b/tplus/evm/constants.py @@ -1,2 +1,2 @@ -REGISTRY_ADDRESS = "0xBBd0020ae0DAB578515d0c72EdFf37Bf30D31BE5" +REGISTRY_ADDRESS = "0x9700c54DFB6C8a77bA151556a41dC035B60e4B91" LATEST_ARB_DEPOSIT_VAULT = "0x7a9eAA74eF31ed3eca5447252b443651Ad250916" diff --git a/tplus/evm/contracts.py b/tplus/evm/contracts.py index 09be522..388e6ea 100644 --- a/tplus/evm/contracts.py +++ b/tplus/evm/contracts.py @@ -17,6 +17,7 @@ from tplus.evm.constants import LATEST_ARB_DEPOSIT_VAULT, REGISTRY_ADDRESS from tplus.evm.exceptions import ContractNotExists from tplus.model.asset_identifier import ChainAddress +from tplus.model.config import ChainConfig from tplus.model.types import ChainID, UserPublicKey from tplus.utils.bytes32 import to_bytes32 @@ -193,6 +194,10 @@ def __init__( ) -> None: self._deployments: dict[int, ContractInstance] = {} self._default_deployer = default_deployer + + if isinstance(chain_id, int): + chain_id = ChainID.evm(chain_id) + self._chain_id = chain_id self._address = address self._tplus_contracts_version = tplus_contracts_version @@ -200,6 +205,10 @@ def __init__( if address is not None and chain_id is not None: self._deployments[f"{chain_id}"] = self._contract_container.at(address) + @property + def chain_address(self) -> ChainAddress: + return ChainAddress(f"{to_bytes32(self.address).hex()}@{self.chain_id}") + @classmethod def deploy(cls, *args, sender: AccountAPI, **kwargs) -> "TPlusContract": tplus_contracts_version = kwargs.pop("tplus_contracts_version", None) @@ -216,7 +225,7 @@ def deploy(cls, *args, sender: AccountAPI, **kwargs) -> "TPlusContract": @classmethod def deploy_dev(cls, **kwargs): - owner = get_dev_default_owner() + owner = kwargs.get("sender") or get_dev_default_owner() return cls.deploy(owner, sender=owner) def __repr__(self) -> str: @@ -234,6 +243,10 @@ def __getattr__(self, attr_name: str): def name(self) -> str: return self.__class__.NAME + @property + def chain_id(self) -> ChainID: + return self._chain_id or ChainID.evm(self.chain_manager.chain_id) + @property def address(self) -> str: if address := self._address: @@ -406,7 +419,7 @@ def from_chain_address(cls, chain_address: ChainAddress) -> "DepositVault": @property def domain_separator(self) -> HexBytes: - return HexBytes(self.chain_manager.provider.get_storage(self.address, 1)) + return HexBytes(self.chain_manager.provider.get_storage(self.address, 2)) def deposit( self, @@ -459,9 +472,7 @@ def execute_atomic_settlement( @classmethod def deploy(cls, *args, sender: AccountAPI, **kwargs) -> "DepositVault": args = list(args) - args[0] = args[0] if args else sender address = sender.get_deployment_address() - instance = super().deploy(*args, sender=sender, **kwargs) if instance.address != address: @@ -525,7 +536,7 @@ class CredentialManager(TPlusContract): @classmethod def deploy_dev(cls, **kwargs) -> "ReceiptAPI": - owner = kwargs.get("owner") or get_dev_default_owner() + owner = kwargs.get("sender") or get_dev_default_owner() operators = kwargs.get("operators", [owner.address]) threshold = kwargs.get("quorum_threshold") or len(operators) registry_address = kwargs.get("registry") or ZERO_ADDRESS @@ -542,13 +553,28 @@ def deploy_dev(cls, **kwargs) -> "ReceiptAPI": sender=owner, ) - def add_vault(self, address: AddressType, chain_id: ChainID | None = None, **kwargs): - if not isinstance(address, str): - # Allow ENS or certain classes to work. - address = self.conversion_manager.convert(address, AddressType) + @property + def governance_nonce(self) -> int: + return self.contract.governanceNonce() - chain_id = chain_id or ChainID.evm(self.chain_manager.chain_id) - return self.contract.addVault(address, chain_id, **kwargs) + def add_vault( + self, + address: ChainAddress, + config: ChainConfig, + signers: list[AddressType], + signatures: list[bytes], + **kwargs, + ): + chain_id = address.chain_id + return self.contract.addVault( + chain_id.routing_id, + chain_id.vm_id, + address.address, + config, + signers, + signatures, + **kwargs, + ) def get_vaults(self) -> list[tuple[bytes, int]]: return [(r.vaultAddress, r.chain) for r in self.contract.getVaults()] diff --git a/tplus/evm/managers/credential_manager.py b/tplus/evm/managers/credential_manager.py index 245b04a..2022042 100644 --- a/tplus/evm/managers/credential_manager.py +++ b/tplus/evm/managers/credential_manager.py @@ -1,8 +1,15 @@ +from functools import cached_property from typing import TYPE_CHECKING from ape.utils.basemodel import ManagerAccessMixin +from eip712 import EIP712Domain, EIP712Message +from eth_abi import encode +from eth_pydantic_types.abi import bytes32, uint256 +from eth_utils import keccak -from tplus.evm.contracts import CredentialManager +from tplus.evm.contracts import CredentialManager, DepositVault +from tplus.model.asset_identifier import ChainAddress +from tplus.model.config import ChainConfig from tplus.model.types import ChainID from tplus.utils.timeout import wait_for_condition @@ -13,6 +20,38 @@ from tplus.client.clearingengine import ClearingEngineClient +OP_ADD_VAULT = keccak(b"OP_ADD_VAULT") + + +def create_domain(credential_manager: "AddressType", chain_id: int | ChainID) -> EIP712Domain: + if isinstance(chain_id, ChainID): + chain_id = chain_id.vm_id + + return EIP712Domain( + name="CredentialManager", + version="1", + chainId=chain_id, + verifyingContract=credential_manager, + ) + + +def create_action( + op_type: bytes, params_hash: bytes, nonce: int, domain: EIP712Domain +) -> EIP712Message: + class Action(EIP712Message): + eip712_domain = domain + + opType: bytes32 + paramsHash: bytes32 + nonce: uint256 + + return Action(opType=op_type, paramsHash=params_hash, nonce=nonce) + + +def sort_accounts(accounts: list["AccountAPI"]) -> list["AccountAPI"]: + return sorted(accounts, key=lambda a: int(a.address, 16)) + + class CredentialManagerOwner(ManagerAccessMixin): """ Owner utilities for the credential manager @@ -20,12 +59,14 @@ class CredentialManagerOwner(ManagerAccessMixin): def __init__( self, - owner: "AccountAPI", + admin: "AddressType", + signers: list["AccountAPI"], credential_manager: CredentialManager | None = None, chain_id: ChainID | None = None, clearing_engine: "ClearingEngineClient | None" = None, ): - self.owner = owner + self.admin = admin + self.signers = signers self.chain_id = chain_id or ChainID.evm(self.chain_manager.chain_id) if credential_manager is None: @@ -35,20 +76,51 @@ def __init__( self.ce = clearing_engine - async def add_vault(self, vault: "AddressType", wait: bool = False, **tx_kwargs): + @property + def governance_nonce(self) -> int: + return self.credential_manager.governance_nonce + + @cached_property + def domain(self) -> EIP712Domain: + return create_domain(self.credential_manager.address, self.chain_id) + + async def add_vault( + self, + vault: ChainAddress | DepositVault, + chain_config: ChainConfig, + wait: bool = False, + **tx_kwargs, + ): """ Add a vault to the registry. Args: - vault (AddressType): The vault to add. + vault (ChainAddress): The address and chain of the vault. + chain_config (ChainConfig): The chain configuration for the chain the vault is deployed on. wait (bool): If true and the CE exists, will wait for the vault to be registered in the CE. tx_kwargs: Additional tx kwargs. Returns: ReceiptAPI """ - tx_kwargs.setdefault("sender", self.owner) - tx = self.credential_manager.add_vault(vault, self.chain_manager.chain_id, **tx_kwargs) + if isinstance(vault, DepositVault): + vault = vault.chain_address + + sender = tx_kwargs["sender"] + if sender == self.admin: + signers = [] + signatures = [] + else: + params_hash = self._encode_add_vault_params(vault, chain_config) + signers = sort_accounts(self.signers) + signatures = self._get_signatures( + OP_ADD_VAULT, + params_hash, + ) + + tx = self.credential_manager.add_vault( + vault, chain_config, signers, signatures, **tx_kwargs + ) if wait: if not (ce := self.ce): @@ -57,7 +129,7 @@ async def add_vault(self, vault: "AddressType", wait: bool = False, **tx_kwargs) await wait_for_condition( update_fn=lambda: ce.vaults.update(), get_fn=lambda: ce.vaults.get(), - # cond: checks if the vault EVM address is part any of the ChainAddress returned. + # cond: checks if the vault address is part any of the ChainAddress returned. check_fn=lambda vaults: any(vault in vault_ca for vault_ca in vaults), timeout=10, interval=1, @@ -65,3 +137,44 @@ async def add_vault(self, vault: "AddressType", wait: bool = False, **tx_kwargs) ) return tx + + def _encode_add_vault_params(self, vault: ChainAddress, chain_config: ChainConfig) -> bytes: + encoded = encode( + ["uint256", "uint256", "address", "(" + ",".join(chain_config.abi_types) + ")"], + [ + vault.chain_id.routing_id, + vault.chain_id.vm_id, + vault.evm_address, + tuple(chain_config.abi_values), + ], + ) + return keccak(encoded) + + def _get_signatures( + self, + op_type: bytes, + params_hash: bytes, + count: int | None = None, + ) -> list[bytes]: + action = self._create_action(op_type, params_hash) + signers = sort_accounts(self.signers) + if count is None: + count = len(self.signers) + + signatures = [] + for acct in signers[:count]: + if signature := acct.sign_message(action): + signatures.append(signature.encode_rsv()) + + return signatures + + def _create_action( + self, + op_type: bytes, + params_hash: bytes, + nonce: int | None = None, + ) -> EIP712Message: + if nonce is None: + nonce = self.governance_nonce + + return create_action(op_type, params_hash, nonce, self.domain) diff --git a/tplus/model/asset_identifier.py b/tplus/model/asset_identifier.py index 37bcfe0..f155e19 100644 --- a/tplus/model/asset_identifier.py +++ b/tplus/model/asset_identifier.py @@ -129,7 +129,7 @@ def evm_address(self) -> str: return to_checksum_address(address) @cached_property - def chain_id(self) -> str: + def chain_id(self) -> ChainID: return ChainID(self.root.split("@")[-1]) diff --git a/tplus/model/config.py b/tplus/model/config.py new file mode 100644 index 0000000..221d22c --- /dev/null +++ b/tplus/model/config.py @@ -0,0 +1,70 @@ +from eth_abi import encode +from pydantic import BaseModel + + +class ChainConfig(BaseModel): + """ + Configure chains in the vault registry. + """ + + blockTimeMs: int + """ + Approximate block time in milliseconds. + """ + + defaultConfirmations: int + """ + The default amount of confirmations to wait for an event to ingest. + """ + + depositIngestConfirmations: int + """ + The amount of confirmations to wait for a deposit to ingest. + """ + + withdrawalIngestConfirmations: int + """ + The amount of confirmations to wait for a withdrawal to ingest. + """ + + settlementIngestConfirmations: int + """ + The amount of confirmations to wait for a settlement to ingest. + """ + + @classmethod + def dev(cls) -> "ChainConfig": + return cls( + blockTimeMs=0, + defaultConfirmations=0, + depositIngestConfirmations=0, + withdrawalIngestConfirmations=0, + settlementIngestConfirmations=0, + ) + + @property + def abi_types(self) -> list[str]: + return [ + "uint64", + "uint8", + "uint8", + "uint8", + "uint8", + ] + + @property + def abi_values(self) -> tuple[str]: + return ( + self.blockTimeMs, + self.defaultConfirmations, + self.depositIngestConfirmations, + self.withdrawalIngestConfirmations, + self.settlementIngestConfirmations, + ) + + def abi_encode(self) -> bytes: + """ + Full ABI encoding of the struct + equivalent to abi.encode(ChainConfig). + """ + return encode(self.abi_types, self.abi_values) From d49cce5ff97132e5573053482380e71c38901c46 Mon Sep 17 00:00:00 2001 From: antazoey Date: Wed, 11 Feb 2026 15:06:47 -0600 Subject: [PATCH 06/16] feat: at method --- tplus/evm/contracts.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tplus/evm/contracts.py b/tplus/evm/contracts.py index 388e6ea..95cb3ab 100644 --- a/tplus/evm/contracts.py +++ b/tplus/evm/contracts.py @@ -205,6 +205,10 @@ def __init__( if address is not None and chain_id is not None: self._deployments[f"{chain_id}"] = self._contract_container.at(address) + @classmethod + def at(cls, address: str) -> "TPlusContract": + return cls(address=address, chain_id=cls.chain_manager.chain_id) + @property def chain_address(self) -> ChainAddress: return ChainAddress(f"{to_bytes32(self.address).hex()}@{self.chain_id}") From 3f304d7ebef19d2862000b17d4e727ee8eabbea7 Mon Sep 17 00:00:00 2001 From: antazoey Date: Wed, 11 Feb 2026 16:42:02 -0600 Subject: [PATCH 07/16] move chainaddr to its own mod --- tplus/model/asset_identifier.py | 134 +------------------------------- tplus/model/chain_address.py | 133 +++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 131 deletions(-) create mode 100644 tplus/model/chain_address.py diff --git a/tplus/model/asset_identifier.py b/tplus/model/asset_identifier.py index f155e19..d5f52c3 100644 --- a/tplus/model/asset_identifier.py +++ b/tplus/model/asset_identifier.py @@ -1,136 +1,8 @@ -from functools import cached_property from typing import Any -from pydantic import RootModel, model_serializer, model_validator +from pydantic import model_serializer, model_validator -from tplus.model.types import ChainID - - -def _parse_asset_from_dict(data: dict) -> str: - if "Address" in data: - return _parse_chain_address_from_dict(data) - - # Backend sends an Index - elif "Index" in data: - return str(data["Index"]) - - raise ValueError("Invalid dictionary for AssetIdentifier: must have 'Address' or 'Index' key") - - -def _parse_chain_address_from_dict(data: dict) -> str: - if not (addr_data := data.get("Address")): - raise ValueError("Invalid dictionary for ChainAddress: must have 'Address' key") - - # Backend sends a dict with byte arrays for address and chain - if isinstance(addr_data, dict) and "address" in addr_data and "chain" in addr_data: - addr_bytes = bytes(addr_data["address"]) - chain_bytes = bytes(addr_data["chain"]) - addr_hex = addr_bytes.hex() - chain_hex = chain_bytes.hex() - return f"{addr_hex}@{chain_hex}" - - # This case seems ambiguous, but we'll pass it through. - elif isinstance(addr_data, str): - return addr_data - - raise ValueError("Invalid Address") - - -def parse_chain_address(data: str) -> str: - """ - Parse a chain-address str (e.g. AssetIdentifier or VaultAddress). - """ - address, chain_part = data.split("@", 1) - - if address.startswith("0x"): - address = address[2:] - if chain_part.startswith("0x"): - chain_part = chain_part[2:] - if len(chain_part) != 18: - raise ValueError("ChainID must contain 1 byte routing ID and 8 bytes VM ID.") - - # Ensure address is 32 bytes (standard EVM uses 20, but we support multiple chains). - address = bytes.fromhex(address).ljust(32, b"\x00").hex() - - return f"{address}@{chain_part}" - - -def _validate_chain_address(chain_address: str) -> str: - # Case 1: Already validated. - if isinstance(chain_address, ChainAddress): - # Already validated. - return chain_address - - # Case 2: Input is a dictionary from the backend (e.g., from JSON deserialization) - elif isinstance(chain_address, dict): - return _parse_asset_from_dict(chain_address) - - # Case 3: Valid strings. - elif isinstance(chain_address, str): - # Case 3.1: User-friendly string like "0x...address@chain_id" - if "@" in chain_address: - return parse_chain_address(chain_address) - - raise ValueError("Invalid ChainAddress") - - -class ChainAddress(RootModel[str]): - """ - Identifies an address on a chain in format hex_address@hex_chain. - """ - - @model_validator(mode="before") - @classmethod - def _validate_input(cls, data: Any) -> Any: - return _validate_chain_address(data) - - def __str__(self) -> str: - return str(self.root) - - def __contains__(self, key: Any) -> bool: - if isinstance(key, int): - return key == self.chain_id - - elif isinstance(key, str) and key.startswith("0x"): - key_str = key.lstrip("0x") - if len(key_str) % 2 != 0: - key_str = f"0{key_str}" - - key_bytes = bytes.fromhex(key_str) - addr = self.evm_address if len(key_bytes) == 20 else self.address - addr = addr.lstrip("0x") - if len(addr) % 2 != 0: - addr = f"0{addr}" - - return bytes.fromhex(addr) == key_bytes - - # Attemps from the other side before returning False. - return NotImplemented - - @model_serializer - def serialize_model(self) -> str: - return self.root - - @cached_property - def address(self) -> str: - return self.root.split("@", 1)[0] - - @cached_property - def evm_address(self) -> str: - address = f"0x{self.address[:40]}" - - try: - # NOTE: This is installed as a peer-dependency if using [evm] extras. - from eth_utils import to_checksum_address - - except ImportError: - return address # Non-checksummed. - - return to_checksum_address(address) - - @cached_property - def chain_id(self) -> ChainID: - return ChainID(self.root.split("@")[-1]) +from tplus.model.chain_address import ChainAddress, validate_chain_address class AssetIdentifier(ChainAddress): @@ -151,7 +23,7 @@ def _validate_input(cls, data: Any) -> Any: if isinstance(data, int) or isinstance(data, str) and data.isnumeric(): return f"{data}" - return _validate_chain_address(data) + return validate_chain_address(data) def __str__(self) -> str: return str(self.root) diff --git a/tplus/model/chain_address.py b/tplus/model/chain_address.py new file mode 100644 index 0000000..83d0925 --- /dev/null +++ b/tplus/model/chain_address.py @@ -0,0 +1,133 @@ +from functools import cached_property +from typing import Any + +from pydantic import RootModel, model_serializer, model_validator + +from tplus.model.types import ChainID + + +def _parse_asset_from_dict(data: dict) -> str: + if "Address" in data: + return _parse_chain_address_from_dict(data) + + # Backend sends an Index + elif "Index" in data: + return str(data["Index"]) + + raise ValueError("Invalid dictionary for AssetIdentifier: must have 'Address' or 'Index' key") + + +def _parse_chain_address_from_dict(data: dict) -> str: + if not (addr_data := data.get("Address")): + raise ValueError("Invalid dictionary for ChainAddress: must have 'Address' key") + + # Backend sends a dict with byte arrays for address and chain + if isinstance(addr_data, dict) and "address" in addr_data and "chain" in addr_data: + addr_bytes = bytes(addr_data["address"]) + chain_bytes = bytes(addr_data["chain"]) + addr_hex = addr_bytes.hex() + chain_hex = chain_bytes.hex() + return f"{addr_hex}@{chain_hex}" + + # This case seems ambiguous, but we'll pass it through. + elif isinstance(addr_data, str): + return addr_data + + raise ValueError("Invalid Address") + + +def parse_chain_address(data: str) -> str: + """ + Parse a chain-address str (e.g. AssetIdentifier or VaultAddress). + """ + address, chain_part = data.split("@", 1) + + if address.startswith("0x"): + address = address[2:] + if chain_part.startswith("0x"): + chain_part = chain_part[2:] + if len(chain_part) != 18: + raise ValueError("ChainID must contain 1 byte routing ID and 8 bytes VM ID.") + + # Ensure address is 32 bytes (standard EVM uses 20, but we support multiple chains). + address = bytes.fromhex(address).ljust(32, b"\x00").hex() + + return f"{address}@{chain_part}" + + +def validate_chain_address(chain_address: str) -> str: + # Case 1: Already validated. + if isinstance(chain_address, ChainAddress): + # Already validated. + return chain_address + + # Case 2: Input is a dictionary from the backend (e.g., from JSON deserialization) + elif isinstance(chain_address, dict): + return _parse_asset_from_dict(chain_address) + + # Case 3: Valid strings. + elif isinstance(chain_address, str): + # Case 3.1: User-friendly string like "0x...address@chain_id" + if "@" in chain_address: + return parse_chain_address(chain_address) + + raise ValueError("Invalid ChainAddress") + + +class ChainAddress(RootModel[str]): + """ + Identifies an address on a chain in format hex_address@hex_chain. + """ + + @model_validator(mode="before") + @classmethod + def _validate_input(cls, data: Any) -> Any: + return validate_chain_address(data) + + def __str__(self) -> str: + return str(self.root) + + def __contains__(self, key: Any) -> bool: + if isinstance(key, int): + return key == self.chain_id + + elif isinstance(key, str) and key.startswith("0x"): + key_str = key.lstrip("0x") + if len(key_str) % 2 != 0: + key_str = f"0{key_str}" + + key_bytes = bytes.fromhex(key_str) + addr = self.evm_address if len(key_bytes) == 20 else self.address + addr = addr.lstrip("0x") + if len(addr) % 2 != 0: + addr = f"0{addr}" + + return bytes.fromhex(addr) == key_bytes + + # Attemps from the other side before returning False. + return NotImplemented + + @model_serializer + def serialize_model(self) -> str: + return self.root + + @cached_property + def address(self) -> str: + return self.root.split("@", 1)[0] + + @cached_property + def evm_address(self) -> str: + address = f"0x{self.address[:40]}" + + try: + # NOTE: This is installed as a peer-dependency if using [evm] extras. + from eth_utils import to_checksum_address + + except ImportError: + return address # Non-checksummed. + + return to_checksum_address(address) + + @cached_property + def chain_id(self) -> ChainID: + return ChainID(self.root.split("@")[-1]) From 226301b5e9a160c092a9ac6ade8d32543e1533d6 Mon Sep 17 00:00:00 2001 From: antazoey Date: Wed, 11 Feb 2026 17:08:27 -0600 Subject: [PATCH 08/16] get vaults --- tplus/evm/contracts.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tplus/evm/contracts.py b/tplus/evm/contracts.py index 95cb3ab..67fd6cd 100644 --- a/tplus/evm/contracts.py +++ b/tplus/evm/contracts.py @@ -20,6 +20,7 @@ from tplus.model.config import ChainConfig from tplus.model.types import ChainID, UserPublicKey from tplus.utils.bytes32 import to_bytes32 +from tplus.utils.hex import to_hex if TYPE_CHECKING: from ape.api.transactions import ReceiptAPI @@ -404,7 +405,7 @@ def __getattr__(self, attr_name: str): # Verify chain first. connected_chain = self.chain_manager.chain_id - if connected_chain != self._chain_id: + if connected_chain != self._chain_id.vm_id: # Try to connect. if choice := CHAIN_MAP.get(connected_chain): with self.network_manager.parse_network_choice(choice): @@ -425,6 +426,10 @@ def from_chain_address(cls, chain_address: ChainAddress) -> "DepositVault": def domain_separator(self) -> HexBytes: return HexBytes(self.chain_manager.provider.get_storage(self.address, 2)) + @property + def approved_settlers(self) -> list["AddressType"]: + return self.contract.getApprovedSettlers() + def deposit( self, user: UserPublicKey, @@ -580,8 +585,14 @@ def add_vault( **kwargs, ) - def get_vaults(self) -> list[tuple[bytes, int]]: - return [(r.vaultAddress, r.chain) for r in self.contract.getVaults()] + def get_vaults(self) -> list[DepositVault]: + return [ + DepositVault( + address=to_hex(r.vaultAddress[:20]), + chain_id=ChainID.from_parts(r.routingId, r.vmId), + ) + for r in self.contract.getVaults(0, 1000) + ] def get_evm_vaults(self) -> list[tuple[AddressType, int]]: result = [] From fc63bd74d02c62a5c03742ffc0efbbadff6ae4f9 Mon Sep 17 00:00:00 2001 From: antazoey Date: Wed, 11 Feb 2026 17:11:25 -0600 Subject: [PATCH 09/16] fix: add settler executor convenience method --- tplus/evm/contracts.py | 5 +++++ tplus/evm/managers/vault.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tplus/evm/contracts.py b/tplus/evm/contracts.py index 67fd6cd..bc6b42c 100644 --- a/tplus/evm/contracts.py +++ b/tplus/evm/contracts.py @@ -430,6 +430,11 @@ def domain_separator(self) -> HexBytes: def approved_settlers(self) -> list["AddressType"]: return self.contract.getApprovedSettlers() + def add_settler_executor( + self, settler: UserPublicKey, executor: AddressType, **kwargs + ) -> "ReceiptAPI": + return self.addSettlerExecutor(settler.public_key, executor, **kwargs) + def deposit( self, user: UserPublicKey, diff --git a/tplus/evm/managers/vault.py b/tplus/evm/managers/vault.py index 48b6636..4b9009e 100644 --- a/tplus/evm/managers/vault.py +++ b/tplus/evm/managers/vault.py @@ -85,7 +85,7 @@ async def register_settler( """ executor = self.conversion_manager.convert(executor, AddressType) tx_kwargs.setdefault("sender", self.owner) - tx = self.vault.addSettlerExecutor(settler, executor, **tx_kwargs) + tx = self.vault.add_settler_executor(settler, executor, **tx_kwargs) if wait: if not (ce := self.ce): From b58ec540d832cedba685fe55d6a1e33ec34f34b2 Mon Sep 17 00:00:00 2001 From: antazoey Date: Wed, 11 Feb 2026 18:26:29 -0600 Subject: [PATCH 10/16] Fix: domain separator --- README.md | 2 +- tests/evm/test_contract.py | 8 +++--- tests/evm/test_eip712.py | 32 ----------------------- tests/model/test_asset_identifier.py | 2 +- tests/utils/test_domain.py | 15 +++++++++++ tplus/client/clearingengine/settlement.py | 2 +- tplus/evm/contracts.py | 2 +- tplus/evm/eip712.py | 31 ---------------------- tplus/evm/managers/vault.py | 10 ++----- tplus/model/chain_address.py | 9 +++++++ tplus/model/config.py | 2 +- tplus/utils/domain.py | 28 ++++++++++++++++++++ 12 files changed, 64 insertions(+), 79 deletions(-) delete mode 100644 tests/evm/test_eip712.py create mode 100644 tests/utils/test_domain.py delete mode 100644 tplus/evm/eip712.py create mode 100644 tplus/utils/domain.py diff --git a/README.md b/README.md index 9eeebbc..d020b01 100644 --- a/README.md +++ b/README.md @@ -190,7 +190,7 @@ Sign EIP-712 messages, such as settlements, using the `eip712` library. ```python from ape import accounts, convert, chain -from tplus.evm.eip712 import Order +from tplus.utils.domain import Order from tplus.evm.contracts import vault from tplus.utils.user import UserManager diff --git a/tests/evm/test_contract.py b/tests/evm/test_contract.py index ae4125a..1e65917 100644 --- a/tests/evm/test_contract.py +++ b/tests/evm/test_contract.py @@ -5,9 +5,9 @@ from tplus.evm.constants import REGISTRY_ADDRESS from tplus.evm.contracts import DepositVault, Registry, TPlusContract, _decode_erc20_error -from tplus.evm.eip712 import Domain from tplus.evm.exceptions import ContractNotExists from tplus.model.asset_identifier import ChainAddress +from tplus.utils.domain import get_dstack_domain class TestTplusContract: @@ -58,7 +58,9 @@ def test_deploy_different_owner(self, accounts): assert deployer_nonce_after > deployer_nonce_before def test_from_chain_address(self): - address = ChainAddress(root="62622E77D1349Face943C6e7D5c01C61465FE1dc@000000000000aa36a7") + address = ChainAddress.from_str( + "62622E77D1349Face943C6e7D5c01C61465FE1dc@000000000000aa36a7" + ) vault = DepositVault.from_chain_address(address) assert vault.address == address.evm_address @@ -68,7 +70,7 @@ def test_domain_separator(self, accounts, chain): # Sets domain separator automatically. instance = DepositVault.deploy(owner, credential_manager, sender=owner) - expected = Domain(chain.chain_id, instance.address).separator + expected = get_dstack_domain(instance.chain_address) instance.set_domain_separator(expected, sender=owner) # Reads using `eth_getStorageAt()` RPC. diff --git a/tests/evm/test_eip712.py b/tests/evm/test_eip712.py deleted file mode 100644 index fb7aeb3..0000000 --- a/tests/evm/test_eip712.py +++ /dev/null @@ -1,32 +0,0 @@ -import pytest -from ape.utils.misc import ZERO_ADDRESS -from hexbytes import HexBytes - -try: - from ape import convert -except ImportError: - pytest.skip("ape is not installed", allow_module_level=True) - -from tplus.evm.eip712 import Domain, Order -from tplus.utils.user import User - - -def test_settlement_order(chain, signer): - """ - Mostly for demo-ing how to sign an order. - """ - order = Order( - eip712_domain=Domain( - chain.chain_id, - ZERO_ADDRESS, - ), - tokenOut="0x62622E77D1349Face943C6e7D5c01C61465FE1dc", # type: ignore - amountOut=convert("1 ether", int), # type: ignore - tokenIn="0x58372ab62269A52fA636aD7F200d93999595DCAF", # type: ignore - amountIn=convert("1 ether", int), # type: ignore - user=HexBytes(User().public_key), # type: ignore - nonce=1, # type: ignore - validUntil=1000000000, # type: ignore - ) - signature = signer.sign_message(order) - assert signer.check_signature(order, signature) diff --git a/tests/model/test_asset_identifier.py b/tests/model/test_asset_identifier.py index 07bb829..13f8ec7 100644 --- a/tests/model/test_asset_identifier.py +++ b/tests/model/test_asset_identifier.py @@ -6,7 +6,7 @@ class TestChainAddress: @pytest.fixture(scope="class") def chain_address(self): - return ChainAddress(root="62622E77D1349Face943C6e7D5c01C61465FE1dc@000000000000aa36a7") + return ChainAddress.from_str("62622E77D1349Face943C6e7D5c01C61465FE1dc@000000000000aa36a7") def test_address(self, chain_address): assert ( diff --git a/tests/utils/test_domain.py b/tests/utils/test_domain.py new file mode 100644 index 0000000..cd79225 --- /dev/null +++ b/tests/utils/test_domain.py @@ -0,0 +1,15 @@ +from eth_pydantic_types.hex.bytes import HexBytes32 + +from tplus.model.chain_address import ChainAddress +from tplus.utils.domain import get_dstack_domain + + +def test_get_dstack_domain(): + address = "8800a71ad5201f7f3cc519a20c6cdf8c29297ea3000000000000000000000000" + vault = ChainAddress.from_str(f"{address}@000000000000007a69") + actual = get_dstack_domain(vault) + + # Same as what backend produces. + expected = HexBytes32("2fb413e7c1cc1665bf930f80ab45477865105e67f74ffdb1a1ec3f6c05bff9a2") + + assert actual == expected, f"Expected {expected.hex()}, got {actual.hex()}" diff --git a/tplus/client/clearingengine/settlement.py b/tplus/client/clearingengine/settlement.py index 1b78be2..ad2a934 100644 --- a/tplus/client/clearingengine/settlement.py +++ b/tplus/client/clearingengine/settlement.py @@ -118,7 +118,7 @@ async def update_approved_settlers(self, chain_id: ChainID, vault_address: str): chain_id (int): The chain ID to check. vault_address (str): The vault address to check. """ - request = ChainAddress(f"{vault_address}@{chain_id}") + request = ChainAddress.from_str(f"{vault_address}@{chain_id}") json_data = request.model_dump(mode="json") await self._post("settlers/update", json_data=json_data) diff --git a/tplus/evm/contracts.py b/tplus/evm/contracts.py index bc6b42c..5c62837 100644 --- a/tplus/evm/contracts.py +++ b/tplus/evm/contracts.py @@ -212,7 +212,7 @@ def at(cls, address: str) -> "TPlusContract": @property def chain_address(self) -> ChainAddress: - return ChainAddress(f"{to_bytes32(self.address).hex()}@{self.chain_id}") + return ChainAddress.from_str(f"{to_bytes32(self.address).hex()}@{self.chain_id}") @classmethod def deploy(cls, *args, sender: AccountAPI, **kwargs) -> "TPlusContract": diff --git a/tplus/evm/eip712.py b/tplus/evm/eip712.py deleted file mode 100644 index 67ad56f..0000000 --- a/tplus/evm/eip712.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import TYPE_CHECKING - -from eip712.messages import EIP712Domain, EIP712Message -from eth_pydantic_types import abi - -from tplus.model.types import ChainID - -if TYPE_CHECKING: - from ape.types.address import AddressType - - -def Domain(chain_id: int | ChainID, verifying_contract: "AddressType") -> EIP712Domain: - if not isinstance(chain_id, int): - chain_id = chain_id.vm_id - - return EIP712Domain( - name="MyrtleWyckoff", - version="1.0.0", - chainId=chain_id, - verifyingContract=verifying_contract, - ) - - -class Order(EIP712Message): - tokenOut: abi.address - amountOut: abi.uint256 - tokenIn: abi.address - amountIn: abi.uint256 - user: abi.bytes32 - nonce: abi.uint256 - validUntil: abi.uint256 diff --git a/tplus/evm/managers/vault.py b/tplus/evm/managers/vault.py index 4b9009e..06acac8 100644 --- a/tplus/evm/managers/vault.py +++ b/tplus/evm/managers/vault.py @@ -5,9 +5,9 @@ from tplus.client import ClearingEngineClient from tplus.evm.address import public_key_to_address from tplus.evm.contracts import DepositVault -from tplus.evm.eip712 import Domain from tplus.evm.managers.evm import ChainConnectedManager from tplus.model.types import ChainID, UserPublicKey +from tplus.utils.domain import get_dstack_domain from tplus.utils.timeout import wait_for_condition if TYPE_CHECKING: @@ -37,13 +37,7 @@ def __init__( def set_domain_separator(self, domain_separator: bytes, **tx_kwargs) -> "ReceiptAPI": tx_kwargs.setdefault("sender", self.owner) - domain_separator = ( - domain_separator - or Domain( - _chainId_=self.chain_manager.chain_id, # type: ignore - _verifyingContract_=self.vault.address, # type: ignore - )._domain_separator_ - ) + domain_separator = domain_separator or get_dstack_domain(self.vault.chain_address) return self.vault.set_domain_separator(domain_separator, **tx_kwargs) diff --git a/tplus/model/chain_address.py b/tplus/model/chain_address.py index 83d0925..fe4316a 100644 --- a/tplus/model/chain_address.py +++ b/tplus/model/chain_address.py @@ -1,6 +1,7 @@ from functools import cached_property from typing import Any +from eth_pydantic_types.hex.bytes import HexBytes32 from pydantic import RootModel, model_serializer, model_validator from tplus.model.types import ChainID @@ -79,6 +80,10 @@ class ChainAddress(RootModel[str]): Identifies an address on a chain in format hex_address@hex_chain. """ + @classmethod + def from_str(cls, value: str) -> "ChainAddress": + return cls(root=value) + @model_validator(mode="before") @classmethod def _validate_input(cls, data: Any) -> Any: @@ -131,3 +136,7 @@ def evm_address(self) -> str: @cached_property def chain_id(self) -> ChainID: return ChainID(self.root.split("@")[-1]) + + @property + def address_bytes(self) -> HexBytes32: + return HexBytes32.__eth_pydantic_validate__(self.address) diff --git a/tplus/model/config.py b/tplus/model/config.py index 221d22c..1bb8c11 100644 --- a/tplus/model/config.py +++ b/tplus/model/config.py @@ -53,7 +53,7 @@ def abi_types(self) -> list[str]: ] @property - def abi_values(self) -> tuple[str]: + def abi_values(self) -> tuple[int, int, int, int, int]: return ( self.blockTimeMs, self.defaultConfirmations, diff --git a/tplus/utils/domain.py b/tplus/utils/domain.py new file mode 100644 index 0000000..e658265 --- /dev/null +++ b/tplus/utils/domain.py @@ -0,0 +1,28 @@ +from typing import TYPE_CHECKING + +from eth_pydantic_types.hex.bytes import HexBytes32 +from eth_utils import keccak + +if TYPE_CHECKING: + from tplus.model.chain_address import ChainAddress + +# Pre-encoded schema version, 32 bytes +SCHEMA_VERSION = bytes([0] * 31 + [1]) + + +def int_to_bytes32(value: int) -> HexBytes32: + return HexBytes32.__eth_pydantic_validate__(value) + + +def get_dstack_domain(vault: "ChainAddress") -> HexBytes32: + chain = vault.chain_id + + parts = [ + vault.address_bytes, + int_to_bytes32(chain.routing_id), + int_to_bytes32(chain.vm_id), + SCHEMA_VERSION, + ] + + concatenated = b"".join(parts) + return HexBytes32(keccak(concatenated)) From 1f0bf1cb5712762f6f82b3028cd51e197e0b7876 Mon Sep 17 00:00:00 2001 From: antazoey Date: Wed, 11 Feb 2026 19:17:10 -0600 Subject: [PATCH 11/16] fixes --- tplus/client/clearingengine/settlement.py | 7 ++++--- tplus/evm/contracts.py | 2 +- tplus/evm/managers/vault.py | 10 ++++++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tplus/client/clearingengine/settlement.py b/tplus/client/clearingengine/settlement.py index ad2a934..6938b19 100644 --- a/tplus/client/clearingengine/settlement.py +++ b/tplus/client/clearingengine/settlement.py @@ -4,7 +4,7 @@ from tplus.client.clearingengine.base import BaseClearingEngineClient from tplus.model.asset_identifier import ChainAddress from tplus.model.settlement import BatchSettlementRequest, TxSettlementRequest -from tplus.model.types import ChainID +from tplus.model.types import ChainID, UserPublicKey class SettlementClient(BaseClearingEngineClient): @@ -122,11 +122,12 @@ async def update_approved_settlers(self, chain_id: ChainID, vault_address: str): json_data = request.model_dump(mode="json") await self._post("settlers/update", json_data=json_data) - async def get_approved_settlers(self, chain_id: ChainID) -> list[str]: + async def get_approved_settlers(self, chain_id: ChainID) -> list[UserPublicKey]: """ Request that the CE check the deposit vault for new approved settlers. Args: chain_id (int): The chain ID to check. """ - return await self._get(f"settlers/{chain_id}") # type: ignore + result = await self._get(f"settlers/{chain_id}") # type: ignore + return [UserPublicKey.__validate_user__(s) for s in result] diff --git a/tplus/evm/contracts.py b/tplus/evm/contracts.py index 5c62837..adfb334 100644 --- a/tplus/evm/contracts.py +++ b/tplus/evm/contracts.py @@ -433,7 +433,7 @@ def approved_settlers(self) -> list["AddressType"]: def add_settler_executor( self, settler: UserPublicKey, executor: AddressType, **kwargs ) -> "ReceiptAPI": - return self.addSettlerExecutor(settler.public_key, executor, **kwargs) + return self.addSettlerExecutor(settler, executor, **kwargs) def deposit( self, diff --git a/tplus/evm/managers/vault.py b/tplus/evm/managers/vault.py index 06acac8..6d6b879 100644 --- a/tplus/evm/managers/vault.py +++ b/tplus/evm/managers/vault.py @@ -9,6 +9,7 @@ from tplus.model.types import ChainID, UserPublicKey from tplus.utils.domain import get_dstack_domain from tplus.utils.timeout import wait_for_condition +from tplus.utils.user import User if TYPE_CHECKING: from ape.api.accounts import AccountAPI @@ -34,7 +35,9 @@ def __init__( self.vault = vault or DepositVault(chain_id=self.chain_id) self.ce = clearing_engine - def set_domain_separator(self, domain_separator: bytes, **tx_kwargs) -> "ReceiptAPI": + def set_domain_separator( + self, domain_separator: bytes | None = None, **tx_kwargs + ) -> "ReceiptAPI": tx_kwargs.setdefault("sender", self.owner) domain_separator = domain_separator or get_dstack_domain(self.vault.chain_address) @@ -69,7 +72,7 @@ async def set_administrators( async def register_settler( self, - settler: UserPublicKey, + settler: UserPublicKey | User, executor: "AddressType | str | AccountAPI | ContractInstance", wait: bool = False, **tx_kwargs, @@ -77,6 +80,9 @@ async def register_settler( """ Allow a user to settler. Requires being the vault contract owner. """ + if isinstance(settler, User): + settler = settler.public_key + executor = self.conversion_manager.convert(executor, AddressType) tx_kwargs.setdefault("sender", self.owner) tx = self.vault.add_settler_executor(settler, executor, **tx_kwargs) From 8d12a95ec9cc99c4c13aa9364757c34451656e8c Mon Sep 17 00:00:00 2001 From: antazoey Date: Wed, 11 Feb 2026 21:05:39 -0600 Subject: [PATCH 12/16] from evm addr --- tests/model/test_asset_identifier.py | 23 +-------------------- tests/model/test_chain_address.py | 30 ++++++++++++++++++++++++++++ tplus/model/chain_address.py | 10 ++++++++++ 3 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 tests/model/test_chain_address.py diff --git a/tests/model/test_asset_identifier.py b/tests/model/test_asset_identifier.py index 13f8ec7..8677d06 100644 --- a/tests/model/test_asset_identifier.py +++ b/tests/model/test_asset_identifier.py @@ -1,27 +1,6 @@ import pytest -from tplus.model.asset_identifier import AssetIdentifier, ChainAddress - - -class TestChainAddress: - @pytest.fixture(scope="class") - def chain_address(self): - return ChainAddress.from_str("62622E77D1349Face943C6e7D5c01C61465FE1dc@000000000000aa36a7") - - def test_address(self, chain_address): - assert ( - chain_address.address - == "62622e77d1349face943c6e7d5c01c61465fe1dc000000000000000000000000" - ) - - def test_evm_address(self, chain_address): - """ - Evm address should be 20 bytes and checksummed. - """ - assert chain_address.evm_address == "0x62622E77D1349Face943C6e7D5c01C61465FE1dc" - - def test_chain_id(self, chain_address): - assert chain_address.chain_id.vm_id == 11155111 +from tplus.model.asset_identifier import AssetIdentifier class TestAssetIdentifier: diff --git a/tests/model/test_chain_address.py b/tests/model/test_chain_address.py new file mode 100644 index 0000000..aa4ec7c --- /dev/null +++ b/tests/model/test_chain_address.py @@ -0,0 +1,30 @@ +import pytest + +from tplus.model.asset_identifier import ChainAddress + + +class TestChainAddress: + @pytest.fixture(scope="class") + def chain_address(self): + return ChainAddress.from_str("62622E77D1349Face943C6e7D5c01C61465FE1dc@000000000000aa36a7") + + def test_from_evm_address(self): + evm_address = "62622E77D1349Face943C6e7D5c01C61465FE1dc" + chain_address = ChainAddress.from_evm_address(evm_address, 123) + assert chain_address.evm_address == f"0x{evm_address}" + assert chain_address.chain_id.vm_id == 123 + + def test_address(self, chain_address): + assert ( + chain_address.address + == "62622e77d1349face943c6e7d5c01c61465fe1dc000000000000000000000000" + ) + + def test_evm_address(self, chain_address): + """ + Evm address should be 20 bytes and checksummed. + """ + assert chain_address.evm_address == "0x62622E77D1349Face943C6e7D5c01C61465FE1dc" + + def test_chain_id(self, chain_address): + assert chain_address.chain_id.vm_id == 11155111 diff --git a/tplus/model/chain_address.py b/tplus/model/chain_address.py index fe4316a..1fdbd54 100644 --- a/tplus/model/chain_address.py +++ b/tplus/model/chain_address.py @@ -84,6 +84,16 @@ class ChainAddress(RootModel[str]): def from_str(cls, value: str) -> "ChainAddress": return cls(root=value) + @classmethod + def from_evm_address(cls, value: str, chain_id: int | ChainID) -> "ChainAddress": + value = value.lower().removeprefix("0x") + value = value.ljust(64, "0") + + if isinstance(chain_id, int): + chain_id = ChainID.evm(chain_id) + + return cls.from_str(f"{value}@{chain_id}") + @model_validator(mode="before") @classmethod def _validate_input(cls, data: Any) -> Any: From 344f1f6889c817bb92d6d922d9d27b2e0adf4088 Mon Sep 17 00:00:00 2001 From: antazoey Date: Thu, 12 Feb 2026 18:02:02 -0600 Subject: [PATCH 13/16] fix problems found from review --- tplus/evm/contracts.py | 15 --------------- tplus/model/chain_address.py | 7 +++---- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/tplus/evm/contracts.py b/tplus/evm/contracts.py index adfb334..0c4cc0a 100644 --- a/tplus/evm/contracts.py +++ b/tplus/evm/contracts.py @@ -599,21 +599,6 @@ def get_vaults(self) -> list[DepositVault]: for r in self.contract.getVaults(0, 1000) ] - def get_evm_vaults(self) -> list[tuple[AddressType, int]]: - result = [] - for res in self.get_vaults(): - addr = res[0] - if addr[20:] == b"\x00" * 12: - addr_bytes = addr[:20] - addr_str = f"0x{addr_bytes.hex()}" - - # Checksum it. - checksummed_addr = self.network_manager.ethereum.decode_address(addr_str) - - result.append((checksummed_addr, res[1])) - - return result - registry = Registry() vault = DepositVault() diff --git a/tplus/model/chain_address.py b/tplus/model/chain_address.py index 1fdbd54..883c7cf 100644 --- a/tplus/model/chain_address.py +++ b/tplus/model/chain_address.py @@ -107,20 +107,19 @@ def __contains__(self, key: Any) -> bool: return key == self.chain_id elif isinstance(key, str) and key.startswith("0x"): - key_str = key.lstrip("0x") + key_str = key.removeprefix("0x") if len(key_str) % 2 != 0: key_str = f"0{key_str}" key_bytes = bytes.fromhex(key_str) addr = self.evm_address if len(key_bytes) == 20 else self.address - addr = addr.lstrip("0x") + addr = addr.removeprefix("0x") if len(addr) % 2 != 0: addr = f"0{addr}" return bytes.fromhex(addr) == key_bytes - # Attemps from the other side before returning False. - return NotImplemented + return False @model_serializer def serialize_model(self) -> str: From 7084887c10ffe4c56138d792c005e4ee63b45bf7 Mon Sep 17 00:00:00 2001 From: antazoey Date: Thu, 12 Feb 2026 18:11:29 -0600 Subject: [PATCH 14/16] fix amount type --- tests/utils/test_decimals.py | 26 +++++++++++++------------- tplus/evm/managers/settle.py | 29 ++++++++++++++++------------- tplus/model/settlement.py | 6 +++--- tplus/utils/amount.py | 17 +++++++++++++---- tplus/utils/decimals.py | 10 +++++----- 5 files changed, 50 insertions(+), 38 deletions(-) diff --git a/tests/utils/test_decimals.py b/tests/utils/test_decimals.py index c0a8ffe..faf7f61 100644 --- a/tests/utils/test_decimals.py +++ b/tests/utils/test_decimals.py @@ -2,34 +2,34 @@ from tplus.constants import CLEARING_ENGINE_DECIMALS from tplus.utils.decimals import ( - normalize_decimals, - normalize_from_inventory, - normalize_to_inventory, + convert_decimals, + to_chain_decimals, + to_inventory_decimals, ) def test_normalize_decimals_equal(): - assert normalize_decimals(12345, 6, 6, "down") == 12345 + assert convert_decimals(12345, 6, 6, "down") == 12345 def test_normalize_decimals_scale_up(): # from 6 decimals to 18 decimals amount = 12345 - result = normalize_decimals(amount, 6, 18, "down") + result = convert_decimals(amount, 6, 18, "down") assert result == amount * 10**12 def test_normalize_decimals_scale_down_round_down(): # from 18 decimals to 6 decimals, round down amount = 123456789000000000000 # 123.456789 tokens at 18 decimals - result = normalize_decimals(amount, 18, 6, "down") + result = convert_decimals(amount, 18, 6, "down") assert result == amount // 10**12 def test_normalize_decimals_scale_down_round_up(): # from 18 decimals to 6 decimals, round up amount = 123456789000000000001 # just slightly above - result = normalize_decimals(amount, 18, 6, "up") + result = convert_decimals(amount, 18, 6, "up") expected = (amount + (10**12 - 1)) // 10**12 assert result == expected # Verify it's strictly greater than floor division @@ -39,16 +39,16 @@ def test_normalize_decimals_scale_down_round_up(): def test_normalize_to_inventory_matches_manual(): amount = 1000 decimals = 6 - result = normalize_to_inventory(amount, decimals, "down") - expected = normalize_decimals(amount, decimals, CLEARING_ENGINE_DECIMALS, "down") + result = to_inventory_decimals(amount, decimals, "down") + expected = convert_decimals(amount, decimals, CLEARING_ENGINE_DECIMALS, "down") assert result == expected def test_normalize_from_inventory_matches_manual(): amount = 10**18 # 1.0 in 18-decimal units decimals = 6 - result = normalize_from_inventory(amount, decimals, "down") - expected = normalize_decimals(amount, CLEARING_ENGINE_DECIMALS, decimals, "down") + result = to_chain_decimals(amount, decimals, "down") + expected = convert_decimals(amount, CLEARING_ENGINE_DECIMALS, decimals, "down") assert result == expected @@ -60,8 +60,8 @@ def test_roundtrip_invertible(rounding): """ amount = 987654321 decimals = 6 - to_inventory = normalize_to_inventory(amount, decimals, rounding) - back = normalize_from_inventory(to_inventory, decimals, rounding) + to_inventory = to_inventory_decimals(amount, decimals, rounding) + back = to_chain_decimals(to_inventory, decimals, rounding) if rounding == "down": assert back == amount diff --git a/tplus/evm/managers/settle.py b/tplus/evm/managers/settle.py index 7abf393..66a9cfd 100644 --- a/tplus/evm/managers/settle.py +++ b/tplus/evm/managers/settle.py @@ -13,7 +13,7 @@ from tplus.logger import get_logger from tplus.model.settlement import TxSettlementRequest from tplus.model.types import ChainID -from tplus.utils.amount import AmountPair +from tplus.utils.amount import Amount from tplus.utils.user.decrypt import decrypt_settlement_approval if TYPE_CHECKING: @@ -34,9 +34,9 @@ class SettlementInfo: """ asset_in: "AssetIdentifier" - amount_in: AmountPair + amount_in: Amount asset_out: "AssetIdentifier" - amount_out: AmountPair + amount_out: Amount expected_nonce: int @@ -139,9 +139,9 @@ def _decrypt_settlement_approval_message(self, message: dict) -> dict | None: async def init_settlement( self, asset_in: "AssetIdentifier", - amount_in: AmountPair, + amount_in: Amount, asset_out: "AssetIdentifier", - amount_out: AmountPair, + amount_out: Amount, ) -> SettlementInfo: """ Initialize a settlement asynchronously without waiting for approval. @@ -161,13 +161,16 @@ async def init_settlement( # Get the expected nonce (current count before this settlement - it will increment after init) expected_nonce = self.vault.settlementCounts(self.tplus_user.public_key) + amount_in_normalized = amount_in.to_inventory_amount("up") + amount_out_normalized = amount_out.to_inventory_amount("down") + request = TxSettlementRequest.create_signed( { "chain_id": self.chain_id, "asset_in": asset_in, - "amount_in": amount_in.normalized, + "amount_in": amount_in_normalized, "asset_out": asset_out, - "amount_out": amount_out.normalized, + "amount_out": amount_out_normalized, }, self.tplus_user, ) @@ -175,8 +178,8 @@ async def init_settlement( self.logger.info( f"Initialized settlement - Asset in: {asset_in.evm_address}, " - f"Amount in: {amount_in.atomic}, Asset out: {asset_out.evm_address}, " - f"Amount out: {amount_out.atomic}, Expected nonce: {expected_nonce}" + f"Amount in: {amount_in.amount}, Asset out: {asset_out.evm_address}, " + f"Amount out: {amount_out.amount}, Expected nonce: {expected_nonce}" ) return SettlementInfo( @@ -226,9 +229,9 @@ async def execute_settlement( f"Chain ID: {self.chain_id}, " f"User: {self.tplus_user.public_key}, " f"Asset in: {settlement_info.asset_in.evm_address}, " - f"Amount in: {settlement_info.amount_in.atomic}, " + f"Amount in: {settlement_info.amount_in.amount}, " f"Asset out: {settlement_info.asset_out.evm_address}, " - f"Amount out: {settlement_info.amount_out.atomic}, " + f"Amount out: {settlement_info.amount_out.amount}, " f"Nonce: {nonce}, " f"Expiry: {expiry}, " f"Domain separator: {self.vault.domain_separator.hex()}" @@ -238,9 +241,9 @@ async def execute_settlement( tx = self.settlement_vault.execute_atomic_settlement( { "tokenIn": settlement_info.asset_in.evm_address, - "amountIn": settlement_info.amount_in.atomic, + "amountIn": settlement_info.amount_in.amount, "tokenOut": settlement_info.asset_out.evm_address, - "amountOut": settlement_info.amount_out.atomic, + "amountOut": settlement_info.amount_out.amount, "nonce": nonce, }, HexBytes(self.tplus_user.public_key), diff --git a/tplus/model/settlement.py b/tplus/model/settlement.py index 785c04f..fd934b7 100644 --- a/tplus/model/settlement.py +++ b/tplus/model/settlement.py @@ -7,7 +7,7 @@ from tplus.model.asset_identifier import AssetIdentifier from tplus.model.types import ChainID, UserPublicKey -from tplus.utils.decimals import normalize_to_inventory +from tplus.utils.decimals import to_inventory_decimals from tplus.utils.hex import str_to_vec if TYPE_CHECKING: @@ -81,9 +81,9 @@ def from_raw( return cls.model_validate( { "asset_in": asset_in, - "amount_in": normalize_to_inventory(amount_in, decimals_in, "up"), + "amount_in": to_inventory_decimals(amount_in, decimals_in, "up"), "asset_out": asset_out, - "amount_out": normalize_to_inventory(amount_out, decimals_out, "down"), + "amount_out": to_inventory_decimals(amount_out, decimals_out, "down"), "tplus_user": tplus_user, "settler": settler or tplus_user, "chain_id": chain, diff --git a/tplus/utils/amount.py b/tplus/utils/amount.py index 83ce1cf..a44736d 100644 --- a/tplus/utils/amount.py +++ b/tplus/utils/amount.py @@ -1,13 +1,22 @@ -from typing import NamedTuple +from pydantic import BaseModel +from tplus.utils.decimals import to_inventory_decimals -class AmountPair(NamedTuple): - normalized: int + +class Amount(BaseModel): + """ + Amount with decimals. + """ + + amount: int """ An amount normalized to clearing-engine decimals. """ - atomic: int + decimals: int """ An atomic amount. """ + + def to_inventory_amount(self, rounding: str) -> int: + return to_inventory_decimals(self.amount, self.decimals, rounding) diff --git a/tplus/utils/decimals.py b/tplus/utils/decimals.py index 063f1b5..ff57bb8 100644 --- a/tplus/utils/decimals.py +++ b/tplus/utils/decimals.py @@ -1,21 +1,21 @@ from tplus.constants import CLEARING_ENGINE_DECIMALS -def normalize_to_inventory(amount: int, decimals: int, rounding: str) -> int: +def to_inventory_decimals(amount: int, decimals: int, rounding: str) -> int: """ Normalize from the given decimals to the T+ inventory decimals. """ - return normalize_decimals(amount, decimals, CLEARING_ENGINE_DECIMALS, rounding) + return convert_decimals(amount, decimals, CLEARING_ENGINE_DECIMALS, rounding) -def normalize_from_inventory(amount: int, decimals: int, rounding: str) -> int: +def to_chain_decimals(amount: int, decimals: int, rounding: str) -> int: """ Normalize from the T+ inventory decimals to the given decimals. """ - return normalize_decimals(amount, CLEARING_ENGINE_DECIMALS, decimals, rounding) + return convert_decimals(amount, CLEARING_ENGINE_DECIMALS, decimals, rounding) -def normalize_decimals(amount: int, from_decimals: int, to_decimals: int, rounding: str) -> int: +def convert_decimals(amount: int, from_decimals: int, to_decimals: int, rounding: str) -> int: """ Convert `amount` between units with different decimal places. Behaves like the Rust version: scales up or down depending on decimals, From f35083fdd02b8d4a9f1cad0eeca6c49801a0fc55 Mon Sep 17 00:00:00 2001 From: antazoey Date: Thu, 12 Feb 2026 18:11:29 -0600 Subject: [PATCH 15/16] typing concern --- tplus/model/config.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tplus/model/config.py b/tplus/model/config.py index 1bb8c11..5268ec8 100644 --- a/tplus/model/config.py +++ b/tplus/model/config.py @@ -1,4 +1,3 @@ -from eth_abi import encode from pydantic import BaseModel @@ -67,4 +66,10 @@ def abi_encode(self) -> bytes: Full ABI encoding of the struct equivalent to abi.encode(ChainConfig). """ + try: + # Have to do this inline since it is not in the evm namespace. + from eth_abi import encode # type: ignore + except ImportError: + raise ValueError("Install [evm] extras to use abi-encoding feature") + return encode(self.abi_types, self.abi_values) From a9dc720017e921ade1597db4bf47c24fa28b289c Mon Sep 17 00:00:00 2001 From: antazoey Date: Fri, 13 Feb 2026 08:31:15 -0600 Subject: [PATCH 16/16] fix: contains --- tplus/model/chain_address.py | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/tplus/model/chain_address.py b/tplus/model/chain_address.py index 883c7cf..66c171f 100644 --- a/tplus/model/chain_address.py +++ b/tplus/model/chain_address.py @@ -103,23 +103,30 @@ def __str__(self) -> str: return str(self.root) def __contains__(self, key: Any) -> bool: - if isinstance(key, int): - return key == self.chain_id + if isinstance(key, str): + return self._contains_address_str(key) - elif isinstance(key, str) and key.startswith("0x"): - key_str = key.removeprefix("0x") - if len(key_str) % 2 != 0: - key_str = f"0{key_str}" + elif isinstance(key, bytes): + return self._contains_address_bytes(key) - key_bytes = bytes.fromhex(key_str) - addr = self.evm_address if len(key_bytes) == 20 else self.address - addr = addr.removeprefix("0x") - if len(addr) % 2 != 0: - addr = f"0{addr}" + return False - return bytes.fromhex(addr) == key_bytes + def _contains_address_str(self, value: str) -> bool: + key_str = value.removeprefix("0x") + if len(key_str) % 2 != 0: + key_str = f"0{key_str}" - return False + key_bytes = bytes.fromhex(key_str) + return self._contains_address_bytes(key_bytes) + + def _contains_address_bytes(self, value: bytes) -> bool: + addr = self.evm_address if len(value) == 20 else self.address + + addr = addr.removeprefix("0x") + if len(addr) % 2 != 0: + addr = f"0{addr}" + + return bytes.fromhex(addr) == value @model_serializer def serialize_model(self) -> str: