Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60a06040 | 22065605 | 313 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
VotingStrategy
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 200 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {BaseVotingStrategy, IBaseVotingStrategy} from '../BaseVotingStrategy.sol';
import {StateProofVerifier} from './libs/StateProofVerifier.sol';
import {IVotingStrategy, IDataWarehouse} from './interfaces/IVotingStrategy.sol';
import {Errors} from '../libraries/Errors.sol';
import {SlotUtils} from '../libraries/SlotUtils.sol';
enum DelegationMode {
NO_DELEGATION,
VOTING_DELEGATED,
PROPOSITION_DELEGATED,
FULL_POWER_DELEGATED
}
/**
* @title VotingStrategy
* @author BGD Labs
* @notice This contracts overrides the base voting strategy to return specific assets used on the strategy.
* @dev These tokens will be used to get the voting power for proposal voting
*/
contract VotingStrategy is BaseVotingStrategy, IVotingStrategy {
/// @inheritdoc IVotingStrategy
IDataWarehouse public immutable DATA_WAREHOUSE;
/// @inheritdoc IVotingStrategy
uint256 public constant STK_AAVE_SLASHING_EXCHANGE_RATE_PRECISION = 1e18;
/// @inheritdoc IVotingStrategy
uint256 public constant STK_AAVE_SLASHING_EXCHANGE_RATE_SLOT = 81;
/// @inheritdoc IVotingStrategy
uint256 public constant POWER_SCALE_FACTOR = 1e10;
/**
* @param dataWarehouse address of the DataWarehouse contract used to store roots
*/
constructor(address dataWarehouse) BaseVotingStrategy() {
require(dataWarehouse != address(0), Errors.INVALID_DATA_WAREHOUSE);
DATA_WAREHOUSE = IDataWarehouse(dataWarehouse);
}
/// @inheritdoc IVotingStrategy
function getVotingPower(
address asset,
uint128 storageSlot,
uint256 power,
bytes32 blockHash
) public view returns (uint256) {
uint256 votingPower;
if (asset == STK_AAVE()) {
if (storageSlot == BASE_BALANCE_SLOT) {
uint256 slashingExchangeRateSlotValue = DATA_WAREHOUSE
.getRegisteredSlot(
blockHash,
asset,
bytes32(STK_AAVE_SLASHING_EXCHANGE_RATE_SLOT)
);
// casting to uint216 as exchange rate is saved in first 27 bytes of slot
uint256 slashingExchangeRate = uint256(
uint216(slashingExchangeRateSlotValue)
);
// Shifting to take into account how stk aave token balances is structured
votingPower = uint72(power >> (104 + 72)) * POWER_SCALE_FACTOR; // stored delegated voting power was scaled down by POWER_SCALE_FACTOR
DelegationMode delegationMode = DelegationMode(
uint8(power >> (104 + 72 + 72))
);
if (
delegationMode != DelegationMode.VOTING_DELEGATED &&
delegationMode != DelegationMode.FULL_POWER_DELEGATED
) {
// adding user token balance if is not delegating his voting power
votingPower += uint104(power);
}
// applying slashing exchange rate
votingPower =
(votingPower * STK_AAVE_SLASHING_EXCHANGE_RATE_PRECISION) /
slashingExchangeRate;
}
} else if (asset == AAVE()) {
if (storageSlot == BASE_BALANCE_SLOT) {
// Shifting to take into account how aave token v3 balances is structured
votingPower = uint72(power >> (104 + 72)) * POWER_SCALE_FACTOR; // stored delegated voting power was scaled down by POWER_SCALE_FACTOR
DelegationMode delegationMode = DelegationMode(
uint8(power >> (104 + 72 + 72))
);
if (
delegationMode != DelegationMode.VOTING_DELEGATED &&
delegationMode != DelegationMode.FULL_POWER_DELEGATED
) {
votingPower += uint104(power); // adding user token balance if is not delegating his voting power
}
}
} else if (asset == A_AAVE()) {
if (storageSlot == A_AAVE_DELEGATED_STATE_SLOT) {
// Shifting to take into account how aave a token delegation balances is structured
votingPower = uint72(power >> 72) * POWER_SCALE_FACTOR; // stored delegated voting power was scaled down by POWER_SCALE_FACTOR
} else if (storageSlot == A_AAVE_BASE_BALANCE_SLOT) {
// need to get first 120 as its where balance is stored
uint256 powerBalance = uint256(uint120(power));
// next uint8 is for delegationMode
DelegationMode delegationMode = DelegationMode(uint8(power >> (120)));
if (
delegationMode != DelegationMode.VOTING_DELEGATED &&
delegationMode != DelegationMode.FULL_POWER_DELEGATED
) {
votingPower += powerBalance; // adding user token balance if is not delegating his voting power
}
}
}
return votingPower;
}
// @inheritdoc IVotingStrategy
function hasRequiredRoots(bytes32 blockHash) external view {
require(
DATA_WAREHOUSE.getStorageRoots(AAVE(), blockHash) != bytes32(0),
Errors.MISSING_AAVE_ROOTS
);
require(
DATA_WAREHOUSE.getStorageRoots(STK_AAVE(), blockHash) != bytes32(0),
Errors.MISSING_STK_AAVE_ROOTS
);
require(
DATA_WAREHOUSE.getStorageRoots(A_AAVE(), blockHash) != bytes32(0),
Errors.MISSING_A_AAVE_ROOTS
);
require(
DATA_WAREHOUSE.getRegisteredSlot(
blockHash,
STK_AAVE(),
bytes32(STK_AAVE_SLASHING_EXCHANGE_RATE_SLOT)
) > 0,
Errors.MISSING_STK_AAVE_SLASHING_EXCHANGE_RATE
);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IBaseVotingStrategy} from '../interfaces/IBaseVotingStrategy.sol';
import {Errors} from './libraries/Errors.sol';
//import {AaveV3EthereumAssets} from 'aave-address-book/AaveV3Ethereum.sol';
/**
* @title BaseVotingStrategy
* @author BGD Labs
* @notice This contract contains the base logic of a voting strategy, being on governance chain or voting machine chain.
*/
abstract contract BaseVotingStrategy is IBaseVotingStrategy {
function AAVE() public pure virtual returns (address) {
return 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9;
}
function STK_AAVE() public pure virtual returns (address) {
return 0x4da27a545c0c5B758a6BA100e3a049001de870f5;
}
function A_AAVE() public pure virtual returns (address) {
return 0xA700b4eB416Be35b2911fd5Dee80678ff64fF6C9;
}
uint128 public constant BASE_BALANCE_SLOT = 0;
uint128 public constant A_AAVE_BASE_BALANCE_SLOT = 52;
uint128 public constant A_AAVE_DELEGATED_STATE_SLOT = 64;
/// @dev on the constructor we get all the voting assets and emit the different asset configurations
constructor() {
address[] memory votingAssetList = getVotingAssetList();
// Check that voting strategy at least has one asset
require(votingAssetList.length != 0, Errors.NO_VOTING_ASSETS);
for (uint256 i = 0; i < votingAssetList.length; i++) {
for (uint256 j = i + 1; j < votingAssetList.length; j++) {
require(
votingAssetList[i] != votingAssetList[j],
Errors.REPEATED_STRATEGY_ASSET
);
}
VotingAssetConfig memory votingAssetConfig = getVotingAssetConfig(
votingAssetList[i]
);
require(
votingAssetConfig.storageSlots.length > 0,
Errors.EMPTY_ASSET_STORAGE_SLOTS
);
for (uint256 k = 0; k < votingAssetConfig.storageSlots.length; k++) {
for (
uint256 l = k + 1;
l < votingAssetConfig.storageSlots.length;
l++
) {
require(
votingAssetConfig.storageSlots[k] !=
votingAssetConfig.storageSlots[l],
Errors.REPEATED_STRATEGY_ASSET_SLOT
);
}
}
emit VotingAssetAdd(votingAssetList[i], votingAssetConfig.storageSlots);
}
}
/// @inheritdoc IBaseVotingStrategy
function getVotingAssetList() public pure returns (address[] memory) {
address[] memory votingAssets = new address[](3);
votingAssets[0] = AAVE();
votingAssets[1] = STK_AAVE();
votingAssets[2] = A_AAVE();
return votingAssets;
}
/// @inheritdoc IBaseVotingStrategy
function getVotingAssetConfig(
address asset
) public pure returns (VotingAssetConfig memory) {
VotingAssetConfig memory votingAssetConfig;
if (asset == AAVE() || asset == STK_AAVE()) {
votingAssetConfig.storageSlots = new uint128[](1);
votingAssetConfig.storageSlots[0] = BASE_BALANCE_SLOT;
} else if (asset == A_AAVE()) {
votingAssetConfig.storageSlots = new uint128[](2);
votingAssetConfig.storageSlots[0] = A_AAVE_BASE_BALANCE_SLOT;
votingAssetConfig.storageSlots[1] = A_AAVE_DELEGATED_STATE_SLOT;
} else {
return votingAssetConfig;
}
return votingAssetConfig;
}
/// @inheritdoc IBaseVotingStrategy
function isTokenSlotAccepted(
address token,
uint128 slot
) external pure returns (bool) {
VotingAssetConfig memory votingAssetConfig = getVotingAssetConfig(token);
for (uint256 i = 0; i < votingAssetConfig.storageSlots.length; i++) {
if (slot == votingAssetConfig.storageSlots[i]) {
return true;
}
}
return false;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {RLPReader} from './RLPReader.sol';
import {MerklePatriciaProofVerifier} from './MerklePatriciaProofVerifier.sol';
/**
* @title A helper library for verification of Merkle Patricia account and state proofs.
*/
library StateProofVerifier {
using RLPReader for RLPReader.RLPItem;
using RLPReader for bytes;
uint256 constant HEADER_STATE_ROOT_INDEX = 3;
uint256 constant HEADER_NUMBER_INDEX = 8;
uint256 constant HEADER_TIMESTAMP_INDEX = 11;
struct BlockHeader {
bytes32 hash;
bytes32 stateRootHash;
uint256 number;
uint256 timestamp;
}
struct Account {
bool exists;
uint256 nonce;
uint256 balance;
bytes32 storageRoot;
bytes32 codeHash;
}
struct SlotValue {
bool exists;
uint256 value;
}
/**
* @notice Parses block header and verifies its presence onchain within the latest 256 blocks.
* @param _headerRlpBytes RLP-encoded block header.
*/
function verifyBlockHeader(
bytes memory _headerRlpBytes,
bytes32 _blockHash
) internal pure returns (BlockHeader memory) {
BlockHeader memory header = parseBlockHeader(_headerRlpBytes);
require(header.hash == _blockHash, 'blockhash mismatch');
return header;
}
/**
* @notice Parses RLP-encoded block header.
* @param _headerRlpBytes RLP-encoded block header.
*/
function parseBlockHeader(
bytes memory _headerRlpBytes
) internal pure returns (BlockHeader memory) {
BlockHeader memory result;
RLPReader.RLPItem[] memory headerFields = _headerRlpBytes
.toRlpItem()
.toList();
require(headerFields.length > HEADER_TIMESTAMP_INDEX);
result.stateRootHash = bytes32(
headerFields[HEADER_STATE_ROOT_INDEX].toUint()
);
result.number = headerFields[HEADER_NUMBER_INDEX].toUint();
result.timestamp = headerFields[HEADER_TIMESTAMP_INDEX].toUint();
result.hash = keccak256(_headerRlpBytes);
return result;
}
/**
* @notice Verifies Merkle Patricia proof of an account and extracts the account fields.
*
* @param _addressHash Keccak256 hash of the address corresponding to the account.
* @param _stateRootHash MPT root hash of the Ethereum state trie.
*/
function extractAccountFromProof(
bytes32 _addressHash, // keccak256(abi.encodePacked(address))
bytes32 _stateRootHash,
RLPReader.RLPItem[] memory _proof
) internal pure returns (Account memory) {
bytes memory acctRlpBytes = MerklePatriciaProofVerifier.extractProofValue(
_stateRootHash,
abi.encodePacked(_addressHash),
_proof
);
Account memory account;
if (acctRlpBytes.length == 0) {
return account;
}
RLPReader.RLPItem[] memory acctFields = acctRlpBytes.toRlpItem().toList();
require(acctFields.length == 4);
account.exists = true;
account.nonce = acctFields[0].toUint();
account.balance = acctFields[1].toUint();
account.storageRoot = bytes32(acctFields[2].toUint());
account.codeHash = bytes32(acctFields[3].toUint());
return account;
}
/**
* @notice Verifies Merkle Patricia proof of a slot and extracts the slot's value.
*
* @param _slotHash Keccak256 hash of the slot position.
* @param _storageRootHash MPT root hash of the account's storage trie.
*/
function extractSlotValueFromProof(
bytes32 _slotHash,
bytes32 _storageRootHash,
RLPReader.RLPItem[] memory _proof
) internal pure returns (SlotValue memory) {
bytes memory valueRlpBytes = MerklePatriciaProofVerifier.extractProofValue(
_storageRootHash,
abi.encodePacked(_slotHash),
_proof
);
SlotValue memory value;
if (valueRlpBytes.length != 0) {
value.exists = true;
value.value = valueRlpBytes.toRlpItem().toUint();
}
return value;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IDataWarehouse} from './IDataWarehouse.sol';
/**
* @title IVotingStrategy
* @author BGD Labs
* @notice interface containing the methods definitions of the VotingStrategy contract
*/
interface IVotingStrategy {
/**
* @notice method to get the DataWarehouse contract
* @return DataWarehouse contract
*/
function DATA_WAREHOUSE() external view returns (IDataWarehouse);
/**
* @notice method to get the exchange rate precision. Taken from stkTokenV3 contract
* @return exchange rate precission
*/
function STK_AAVE_SLASHING_EXCHANGE_RATE_PRECISION()
external
view
returns (uint256);
/**
* @notice method to get the slot of the stkAave exchange rate in the stkAave contract
* @return stkAave exchange rate slot
*/
function STK_AAVE_SLASHING_EXCHANGE_RATE_SLOT()
external
view
returns (uint256);
/**
* @notice method to get the power scale factor of the delegated balances
* @return power scale factor
*/
function POWER_SCALE_FACTOR() external view returns (uint256);
/**
* @notice method to get the power of an asset
* @param asset address of the token to get the power
* @param storageSlot storage position of the balance mapping
* @param power balance of a determined asset to be used for the vote
* @param blockHash block hash of when we want to get the power. Optional parameter
* @return voting power of the specified asset
*/
function getVotingPower(
address asset,
uint128 storageSlot,
uint256 power,
bytes32 blockHash
) external view returns (uint256);
/**
* @notice method to check that the roots for all the tokens in the voting strategy have been registered. Including
the registry of the stkAave exchange rate slot
* @param blockHash hash of the block from where the roots have been registered.
*/
function hasRequiredRoots(bytes32 blockHash) external view;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title Errors library
* @author BGD Labs
* @notice Defines the error messages emitted by the different contracts of the Aave Governance V3
*/
library Errors {
string public constant VOTING_PORTALS_COUNT_NOT_0 = '1'; // to be able to rescue voting portals count must be 0
string public constant AT_LEAST_ONE_PAYLOAD = '2'; // to create a proposal, it must have at least one payload
string public constant VOTING_PORTAL_NOT_APPROVED = '3'; // the voting portal used to vote on proposal must be approved
string public constant PROPOSITION_POWER_IS_TOO_LOW = '4'; // proposition power of proposal creator must be equal or higher than the specified threshold for the access level
string public constant PROPOSAL_NOT_IN_CREATED_STATE = '5'; // proposal should be in the CREATED state
string public constant PROPOSAL_NOT_IN_ACTIVE_STATE = '6'; // proposal must be in an ACTIVE state
string public constant PROPOSAL_NOT_IN_QUEUED_STATE = '7'; // proposal must be in a QUEUED state
string public constant VOTING_START_COOLDOWN_PERIOD_NOT_PASSED = '8'; // to activate a proposal vote, the cool down delay must pass
string public constant CALLER_NOT_A_VALID_VOTING_PORTAL = '9'; // only an allowed voting portal can queue a proposal
string public constant QUEUE_COOLDOWN_PERIOD_NOT_PASSED = '10'; // to execute a proposal a cooldown delay must pass
string public constant PROPOSAL_NOT_IN_THE_CORRECT_STATE = '11'; // proposal must be created but not executed yet to be able to be canceled
string public constant CALLER_NOT_GOVERNANCE = '12'; // caller must be governance
string public constant VOTER_ALREADY_VOTED_ON_PROPOSAL = '13'; // voter can only vote once per proposal using voting portal
string public constant WRONG_MESSAGE_ORIGIN = '14'; // received message must come from registered source address, chain id, CrossChainController
string public constant NO_VOTING_ASSETS = '15'; // Strategy must have voting assets
string public constant PROPOSAL_VOTE_ALREADY_CREATED = '16'; // vote on proposal can only be created once
string public constant INVALID_SIGNATURE = '17'; // submitted signature is not valid
string public constant PROPOSAL_VOTE_NOT_FINISHED = '18'; // proposal vote must be finished
string public constant PROPOSAL_VOTE_NOT_IN_ACTIVE_STATE = '19'; // proposal vote must be in active state
string public constant PROPOSAL_VOTE_ALREADY_EXISTS = '20'; // proposal vote already exists
string public constant VOTE_ONCE_FOR_ASSET = '21'; // an asset can only be used once per vote
string public constant USER_BALANCE_DOES_NOT_EXISTS = '22'; // to vote an user must have balance in the token the user is voting with
string public constant USER_VOTING_BALANCE_IS_ZERO = '23'; // to vote an user must have some balance between all the tokens selected for voting
string public constant MISSING_AAVE_ROOTS = '24'; // must have AAVE roots registered to use strategy
string public constant MISSING_STK_AAVE_ROOTS = '25'; // must have stkAAVE roots registered to use strategy
string public constant MISSING_STK_AAVE_SLASHING_EXCHANGE_RATE = '26'; // must have stkAAVE slashing exchange rate registered to use strategy
string public constant UNPROCESSED_STORAGE_ROOT = '27'; // root must be registered beforehand
string public constant NOT_ENOUGH_MSG_VALUE = '28'; // method was not called with enough value to execute the call
string public constant FAILED_ACTION_EXECUTION = '29'; // action failed to execute
string public constant SHOULD_BE_AT_LEAST_ONE_EXECUTOR = '30'; // at least one executor is needed
string public constant INVALID_EMPTY_TARGETS = '31'; // target of the payload execution must not be empty
string public constant EXECUTOR_WAS_NOT_SPECIFIED_FOR_REQUESTED_ACCESS_LEVEL =
'32'; // payload executor must be registered for the specified payload access level
string public constant PAYLOAD_NOT_IN_QUEUED_STATE = '33'; // payload must be en the queued state
string public constant TIMELOCK_NOT_FINISHED = '34'; // delay has not passed before execution can be called
string public constant PAYLOAD_NOT_IN_THE_CORRECT_STATE = '35'; // payload must be created but not executed yet to be able to be canceled
string public constant PAYLOAD_NOT_IN_CREATED_STATE = '36'; // payload must be in the created state
string public constant MISSING_A_AAVE_ROOTS = '37'; // must have aAAVE roots registered to use strategy
string public constant MISSING_PROPOSAL_BLOCK_HASH = '38'; // block hash for this proposal was not bridged before
string public constant PROPOSAL_VOTE_CONFIGURATION_ALREADY_BRIDGED = '39'; // configuration for this proposal bridged already
string public constant INVALID_VOTING_PORTAL_ADDRESS = '40'; // voting portal address can't be 0x0
string public constant INVALID_POWER_STRATEGY = '41'; // 0x0 is not valid as the power strategy
string public constant INVALID_EXECUTOR_ADDRESS = '42'; // executor address can't be 0x0
string public constant EXECUTOR_ALREADY_SET_IN_DIFFERENT_LEVEL = '43'; // executor address already being used as executor of a different level
string public constant INVALID_VOTING_DURATION = '44'; // voting duration can not be bigger than the time it takes to execute a proposal
string public constant VOTING_DURATION_NOT_PASSED = '45'; // at least votingDuration should have passed since voting started for a proposal to be queued
string public constant INVALID_PROPOSAL_ACCESS_LEVEL = '46'; // the bridged proposal access level does not correspond with the maximum access level required by the payload
string public constant PAYLOAD_NOT_CREATED_BEFORE_PROPOSAL = '47'; // payload must be created before proposal
string public constant INVALID_CROSS_CHAIN_CONTROLLER_ADDRESS = '48';
string public constant INVALID_MESSAGE_ORIGINATOR_ADDRESS = '49';
string public constant INVALID_ORIGIN_CHAIN_ID = '50';
string public constant INVALID_ACTION_TARGET = '51';
string public constant INVALID_ACTION_ACCESS_LEVEL = '52';
string public constant INVALID_EXECUTOR_ACCESS_LEVEL = '53';
string public constant INVALID_VOTING_PORTAL_CROSS_CHAIN_CONTROLLER = '54';
string public constant INVALID_VOTING_PORTAL_VOTING_MACHINE = '55';
string public constant INVALID_VOTING_PORTAL_GOVERNANCE = '56';
string public constant INVALID_VOTING_MACHINE_CHAIN_ID = '57';
string public constant G_INVALID_CROSS_CHAIN_CONTROLLER_ADDRESS = '58';
string public constant G_INVALID_IPFS_HASH = '59';
string public constant G_INVALID_PAYLOAD_ACCESS_LEVEL = '60';
string public constant G_INVALID_PAYLOADS_CONTROLLER = '61';
string public constant G_INVALID_PAYLOAD_CHAIN = '62';
string public constant POWER_STRATEGY_HAS_NO_TOKENS = '63'; // power strategy should at least have
string public constant INVALID_VOTING_CONFIG_ACCESS_LEVEL = '64';
string public constant VOTING_DURATION_TOO_SMALL = '65';
string public constant NO_BRIDGED_VOTING_ASSETS = '66';
string public constant INVALID_VOTER = '67';
string public constant INVALID_DATA_WAREHOUSE = '68';
string public constant INVALID_VOTING_MACHINE_CROSS_CHAIN_CONTROLLER = '69';
string public constant INVALID_L1_VOTING_PORTAL = '70';
string public constant INVALID_VOTING_PORTAL_CHAIN_ID = '71';
string public constant INVALID_VOTING_STRATEGY = '72';
string public constant INVALID_VOTE_CONFIGURATION_BLOCKHASH = '73';
string public constant INVALID_VOTE_CONFIGURATION_VOTING_DURATION = '74';
string public constant INVALID_GAS_LIMIT = '75';
string public constant INVALID_VOTING_CONFIGS = '76'; // a lvl2 voting configuration must be sent to initializer
string public constant INVALID_EXECUTOR_DELAY = '77';
string public constant REPEATED_STRATEGY_ASSET = '78';
string public constant EMPTY_ASSET_STORAGE_SLOTS = '79';
string public constant REPEATED_STRATEGY_ASSET_SLOT = '80';
string public constant INVALID_EXECUTION_TARGET = '81';
string public constant MISSING_VOTING_CONFIGURATIONS = '82'; // voting configurations for lvl1 and lvl2 must be included on initialization
string public constant INVALID_PROPOSITION_POWER = '83';
string public constant INVALID_YES_THRESHOLD = '84';
string public constant INVALID_YES_NO_DIFFERENTIAL = '85';
string public constant ETH_TRANSFER_FAILED = '86';
string public constant INVALID_INITIAL_VOTING_CONFIGS = '87'; // initial voting configurations can not be of the same level
string public constant INVALID_VOTING_PORTAL_ADDRESS_IN_VOTING_MACHINE = '88';
string public constant INVALID_VOTING_PORTAL_OWNER = '89';
string public constant CANCELLATION_FEE_REDEEM_FAILED = '90'; // cancellation fee was not able to be redeemed
string public constant INVALID_CANCELLATION_FEE_COLLECTOR = '91'; // collector can not be address 0
string public constant INVALID_CANCELLATION_FEE_SENT = '92'; // cancellation fee sent does not match the needed amount
string public constant CANCELLATION_FEE_ALREADY_REDEEMED = '93'; // cancellation fee already redeemed
string public constant INVALID_STATE_TO_REDEEM_CANCELLATION_FEE = '94'; // proposal state is not a valid state to redeem cancellation fee
string public constant MISSING_REPRESENTATION_ROOTS = '95'; // to represent a voter the representation roots need to be registered
string public constant CALLER_IS_NOT_VOTER_REPRESENTATIVE = '96'; // to represent a voter, caller must be the stored representative
string public constant VM_INVALID_GOVERNANCE_ADDRESS = '97'; // governance address can not be 0
string public constant ALL_DELEGATION_ACTIONS_FAILED = '98'; // all meta delegation actions failed on MetaDelegateHelper
string public constant ONLY_BY_PAYLOADS_MANAGER = '99'; // only payloads manager can call this function
string public constant ONLY_BY_PAYLOADS_MANAGER_OR_GUARDIAN = '100'; // only payloads manager or guardian can call this function
string public constant FUNCTION_NOT_SUPPORTED = '101'; // function not supported
string public constant FORBIDDEN_TO_SUBMIT_NON_EXISTENT_ROOTS = '102'; // forbidden to submit non existent account roots
string public constant FORBIDDEN_TO_SUBMIT_NON_EXISTENT_SLOTS = '103'; // forbidden to submit non existent storage slots
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SlotUtils {
/**
* @notice method to calculate the slot hash of the a mapping indexed by account
* @param account address of the balance holder
* @param balanceMappingPosition base position of the storage slot of the balance on a token contract
* @return the slot hash
*/
function getAccountSlotHash(
address account,
uint256 balanceMappingPosition
) internal pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
bytes32(uint256(uint160(account))),
balanceMappingPosition
)
);
}
/**
* @notice method to calculate the slot hash of the a mapping indexed by voter and chainId
* @param voter address of the voter
* @param chainId id of the chain of the votingMachine
* @param representativesMappingPosition base position of the storage slot of the representatives on governance contract
* @return the slot hash
* @dev mapping(address => mapping(uint256 => address))
*/
function getRepresentativeSlotHash(
address voter,
uint256 chainId,
uint256 representativesMappingPosition
) internal pure returns (bytes32) {
bytes32 voterMappingIndex = keccak256(
abi.encodePacked(
bytes32(uint256(uint160(voter))),
representativesMappingPosition
)
);
return
keccak256(abi.encodePacked(bytes32(chainId), uint256(voterMappingIndex)));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IBaseVotingStrategy
* @author BGD Labs
* @notice interface containing the objects, events and method definitions of the BaseVotingStrategy contract
*/
interface IBaseVotingStrategy {
/**
* @notice object storing the information of the asset used for the voting strategy
* @param storageSlots list of slots for the balance of the specified token.
From that slot, by adding the address of the user, the correct balance can be taken.
*/
struct VotingAssetConfig {
uint128[] storageSlots;
}
/**
* @notice emitted when an asset is added for the voting strategy
* @param asset address of the token to be added
* @param storageSlots array of storage positions of the balance mapping
*/
event VotingAssetAdd(address indexed asset, uint128[] storageSlots);
/**
* @notice method to get the AAVE token address
* @return AAVE token contract address
*/
function AAVE() external view returns (address);
/**
* @notice method to get the A_AAVE token address
* @return A_AAVE token contract address
*/
function A_AAVE() external view returns (address);
/**
* @notice method to get the stkAAVE token address
* @return stkAAVE token contract address
*/
function STK_AAVE() external view returns (address);
/**
* @notice method to get the slot of the balance of the AAVE and stkAAVE
* @return AAVE and stkAAVE base balance slot
*/
function BASE_BALANCE_SLOT() external view returns (uint128);
/**
* @notice method to get the slot of the balance of the AAVE aToken
* @return AAVE aToken base balance slot
*/
function A_AAVE_BASE_BALANCE_SLOT() external view returns (uint128);
/**
* @notice method to get the slot of the AAVE aToken delegation state
* @return AAVE aToken delegation state slot
*/
function A_AAVE_DELEGATED_STATE_SLOT() external view returns (uint128);
/**
* @notice method to check if a token and slot combination is accepted
* @param token address of the token to check
* @param slot number of the token slot
* @return flag indicating if the token slot is accepted
*/
function isTokenSlotAccepted(
address token,
uint128 slot
) external view returns (bool);
/**
* @notice method to get the addresses of the assets that can be used for voting
* @return list of addresses of assets
*/
function getVotingAssetList() external view returns (address[] memory);
/**
* @notice method to get the configuration for voting of an asset
* @param asset address of the asset to get the configuration from
* @return object with the asset configuration containing the list of storage slots
*/
function getVotingAssetConfig(
address asset
) external view returns (VotingAssetConfig memory);
}// SPDX-License-Identifier: Apache-2.0 /* * @author Hamdi Allam [email protected] * Please reach out with any questions or concerns * Code copied from: https://github.com/hamdiallam/Solidity-RLP/blob/master/contracts/RLPReader.sol */ pragma solidity ^0.8.0; library RLPReader { uint8 constant STRING_SHORT_START = 0x80; uint8 constant STRING_LONG_START = 0xb8; uint8 constant LIST_SHORT_START = 0xc0; uint8 constant LIST_LONG_START = 0xf8; uint8 constant WORD_SIZE = 32; struct RLPItem { uint256 len; uint256 memPtr; } struct Iterator { RLPItem item; // Item that's being iterated over. uint256 nextPtr; // Position of the next item in the list. } /* * @dev Returns the next element in the iteration. Reverts if it has not next element. * @param self The iterator. * @return The next element in the iteration. */ function next(Iterator memory self) internal pure returns (RLPItem memory) { require(hasNext(self)); uint256 ptr = self.nextPtr; uint256 itemLength = _itemLength(ptr); self.nextPtr = ptr + itemLength; return RLPItem(itemLength, ptr); } /* * @dev Returns true if the iteration has more elements. * @param self The iterator. * @return true if the iteration has more elements. */ function hasNext(Iterator memory self) internal pure returns (bool) { RLPItem memory item = self.item; return self.nextPtr < item.memPtr + item.len; } /* * @param item RLP encoded bytes */ function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) { uint256 memPtr; assembly { memPtr := add(item, 0x20) } return RLPItem(item.length, memPtr); } /* * @dev Create an iterator. Reverts if item is not a list. * @param self The RLP item. * @return An 'Iterator' over the item. */ function iterator( RLPItem memory self ) internal pure returns (Iterator memory) { require(isList(self)); uint256 ptr = self.memPtr + _payloadOffset(self.memPtr); return Iterator(self, ptr); } /* * @param the RLP item. */ function rlpLen(RLPItem memory item) internal pure returns (uint256) { return item.len; } /* * @param the RLP item. * @return (memPtr, len) pair: location of the item's payload in memory. */ function payloadLocation( RLPItem memory item ) internal pure returns (uint256, uint256) { uint256 offset = _payloadOffset(item.memPtr); uint256 memPtr = item.memPtr + offset; uint256 len = item.len - offset; // data length return (memPtr, len); } /* * @param the RLP item. */ function payloadLen(RLPItem memory item) internal pure returns (uint256) { (, uint256 len) = payloadLocation(item); return len; } /* * @param the RLP item containing the encoded list. */ function toList( RLPItem memory item ) internal pure returns (RLPItem[] memory) { require(isList(item)); uint256 items = numItems(item); RLPItem[] memory result = new RLPItem[](items); uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr); uint256 dataLen; for (uint256 i = 0; i < items; i++) { dataLen = _itemLength(memPtr); result[i] = RLPItem(dataLen, memPtr); memPtr = memPtr + dataLen; } return result; } // @return indicator whether encoded payload is a list. negate this function call for isData. function isList(RLPItem memory item) internal pure returns (bool) { if (item.len == 0) return false; uint8 byte0; uint256 memPtr = item.memPtr; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < LIST_SHORT_START) return false; return true; } /* * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory. * @return keccak256 hash of RLP encoded bytes. */ function rlpBytesKeccak256( RLPItem memory item ) internal pure returns (bytes32) { uint256 ptr = item.memPtr; uint256 len = item.len; bytes32 result; assembly { result := keccak256(ptr, len) } return result; } /* * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory. * @return keccak256 hash of the item payload. */ function payloadKeccak256( RLPItem memory item ) internal pure returns (bytes32) { (uint256 memPtr, uint256 len) = payloadLocation(item); bytes32 result; assembly { result := keccak256(memPtr, len) } return result; } /** RLPItem conversions into data types **/ // @returns raw rlp encoding in bytes function toRlpBytes( RLPItem memory item ) internal pure returns (bytes memory) { bytes memory result = new bytes(item.len); if (result.length == 0) return result; uint256 ptr; assembly { ptr := add(0x20, result) } copy(item.memPtr, ptr, item.len); return result; } // any non-zero byte except "0x80" is considered true function toBoolean(RLPItem memory item) internal pure returns (bool) { require(item.len == 1); uint256 result; uint256 memPtr = item.memPtr; assembly { result := byte(0, mload(memPtr)) } // SEE Github Issue #5. // Summary: Most commonly used RLP libraries (i.e Geth) will encode // "0" as "0x80" instead of as "0". We handle this edge case explicitly // here. if (result == 0 || result == STRING_SHORT_START) { return false; } else { return true; } } function toAddress(RLPItem memory item) internal pure returns (address) { // 1 byte for the length prefix require(item.len == 21); return address(uint160(toUint(item))); } function toUint(RLPItem memory item) internal pure returns (uint256) { require(item.len > 0 && item.len <= 33); (uint256 memPtr, uint256 len) = payloadLocation(item); uint256 result; assembly { result := mload(memPtr) // shift to the correct location if neccesary if lt(len, 32) { result := div(result, exp(256, sub(32, len))) } } return result; } // enforces 32 byte length function toUintStrict(RLPItem memory item) internal pure returns (uint256) { // one byte prefix require(item.len == 33); uint256 result; uint256 memPtr = item.memPtr + 1; assembly { result := mload(memPtr) } return result; } function toBytes(RLPItem memory item) internal pure returns (bytes memory) { require(item.len > 0); (uint256 memPtr, uint256 len) = payloadLocation(item); bytes memory result = new bytes(len); uint256 destPtr; assembly { destPtr := add(0x20, result) } copy(memPtr, destPtr, len); return result; } /* * Private Helpers */ // @return number of payload items inside an encoded list. function numItems(RLPItem memory item) private pure returns (uint256) { if (item.len == 0) return 0; uint256 count = 0; uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr); uint256 endPtr = item.memPtr + item.len; while (currPtr < endPtr) { currPtr = currPtr + _itemLength(currPtr); // skip over an item count++; } return count; } // @return entire rlp item byte length function _itemLength(uint256 memPtr) private pure returns (uint256) { uint256 itemLen; uint256 byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) { itemLen = 1; } else if (byte0 < STRING_LONG_START) { itemLen = byte0 - STRING_SHORT_START + 1; } else if (byte0 < LIST_SHORT_START) { assembly { let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is memPtr := add(memPtr, 1) // skip over the first byte /* 32 byte word size */ let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len itemLen := add(dataLen, add(byteLen, 1)) } } else if (byte0 < LIST_LONG_START) { itemLen = byte0 - LIST_SHORT_START + 1; } else { assembly { let byteLen := sub(byte0, 0xf7) memPtr := add(memPtr, 1) let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length itemLen := add(dataLen, add(byteLen, 1)) } } return itemLen; } // @return number of bytes until the data function _payloadOffset(uint256 memPtr) private pure returns (uint256) { uint256 byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) { return 0; } else if ( byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START) ) { return 1; } else if (byte0 < LIST_SHORT_START) { // being explicit return byte0 - (STRING_LONG_START - 1) + 1; } else { return byte0 - (LIST_LONG_START - 1) + 1; } } /* * @param src Pointer to source * @param dest Pointer to destination * @param len Amount of memory to copy from the source */ function copy(uint256 src, uint256 dest, uint256 len) private pure { if (len == 0) return; // copy as many word sizes as possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } src += WORD_SIZE; dest += WORD_SIZE; } if (len > 0) { // left over bytes. Mask is used to remove unwanted bytes from the word uint256 mask = 256 ** (WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) // zero out src let destpart := and(mload(dest), mask) // retrieve the bytes mstore(dest, or(destpart, srcpart)) } } } }
// SPDX-License-Identifier: MIT
/**
* Copied from https://github.com/lidofinance/curve-merkle-oracle/blob/main/contracts/MerklePatriciaProofVerifier.sol
*/
pragma solidity ^0.8.0;
import {RLPReader} from './RLPReader.sol';
library MerklePatriciaProofVerifier {
using RLPReader for RLPReader.RLPItem;
using RLPReader for bytes;
/// @dev Validates a Merkle-Patricia-Trie proof.
/// If the proof proves the inclusion of some key-value pair in the
/// trie, the value is returned. Otherwise, i.e. if the proof proves
/// the exclusion of a key from the trie, an empty byte array is
/// returned.
/// @param rootHash is the Keccak-256 hash of the root node of the MPT.
/// @param path is the key of the node whose inclusion/exclusion we are
/// proving.
/// @param stack is the stack of MPT nodes (starting with the root) that
/// need to be traversed during verification.
/// @return value whose inclusion is proved or an empty byte array for
/// a proof of exclusion
function extractProofValue(
bytes32 rootHash,
bytes memory path,
RLPReader.RLPItem[] memory stack
) internal pure returns (bytes memory value) {
bytes memory mptKey = _decodeNibbles(path, 0);
uint256 mptKeyOffset = 0;
bytes32 nodeHashHash;
RLPReader.RLPItem[] memory node;
RLPReader.RLPItem memory rlpValue;
if (stack.length == 0) {
// Root hash of empty Merkle-Patricia-Trie
require(
rootHash ==
0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421
);
return new bytes(0);
}
// Traverse stack of nodes starting at root.
for (uint256 i = 0; i < stack.length; i++) {
// We use the fact that an rlp encoded list consists of some
// encoding of its length plus the concatenation of its
// *rlp-encoded* items.
// The root node is hashed with Keccak-256 ...
if (i == 0 && rootHash != stack[i].rlpBytesKeccak256()) {
revert();
}
// ... whereas all other nodes are hashed with the MPT
// hash function.
if (i != 0 && nodeHashHash != _mptHashHash(stack[i])) {
revert();
}
// We verified that stack[i] has the correct hash, so we
// may safely decode it.
node = stack[i].toList();
if (node.length == 2) {
// Extension or Leaf node
bool isLeaf;
bytes memory nodeKey;
(isLeaf, nodeKey) = _merklePatriciaCompactDecode(node[0].toBytes());
uint256 prefixLength = _sharedPrefixLength(
mptKeyOffset,
mptKey,
nodeKey
);
mptKeyOffset += prefixLength;
if (prefixLength < nodeKey.length) {
// Proof claims divergent extension or leaf. (Only
// relevant for proofs of exclusion.)
// An Extension/Leaf node is divergent iff it "skips" over
// the point at which a Branch node should have been had the
// excluded key been included in the trie.
// Example: Imagine a proof of exclusion for path [1, 4],
// where the current node is a Leaf node with
// path [1, 3, 3, 7]. For [1, 4] to be included, there
// should have been a Branch node at [1] with a child
// at 3 and a child at 4.
// Sanity check
if (i < stack.length - 1) {
// divergent node must come last in proof
revert();
}
return new bytes(0);
}
if (isLeaf) {
// Sanity check
if (i < stack.length - 1) {
// leaf node must come last in proof
revert();
}
if (mptKeyOffset < mptKey.length) {
return new bytes(0);
}
rlpValue = node[1];
return rlpValue.toBytes();
} else {
// extension
// Sanity check
if (i == stack.length - 1) {
// shouldn't be at last level
revert();
}
if (!node[1].isList()) {
// rlp(child) was at least 32 bytes. node[1] contains
// Keccak256(rlp(child)).
nodeHashHash = node[1].payloadKeccak256();
} else {
// rlp(child) was less than 32 bytes. node[1] contains
// rlp(child).
nodeHashHash = node[1].rlpBytesKeccak256();
}
}
} else if (node.length == 17) {
// Branch node
if (mptKeyOffset != mptKey.length) {
// we haven't consumed the entire path, so we need to look at a child
uint8 nibble = uint8(mptKey[mptKeyOffset]);
mptKeyOffset += 1;
if (nibble >= 16) {
// each element of the path has to be a nibble
revert();
}
if (_isEmptyBytesequence(node[nibble])) {
// Sanity
if (i != stack.length - 1) {
// leaf node should be at last level
revert();
}
return new bytes(0);
} else if (!node[nibble].isList()) {
nodeHashHash = node[nibble].payloadKeccak256();
} else {
nodeHashHash = node[nibble].rlpBytesKeccak256();
}
// sanity check
if (i == stack.length - 1) {
// need to process the child now. Last node can not be a branch node
revert();
}
} else {
// we have consumed the entire mptKey, so we need to look at what's contained in this node.
// Sanity
if (i != stack.length - 1) {
// should be at last level
revert();
}
return node[16].toBytes();
}
}
}
}
/// @dev Computes the hash of the Merkle-Patricia-Trie hash of the RLP item.
/// Merkle-Patricia-Tries use a weird "hash function" that outputs
/// *variable-length* hashes: If the item is shorter than 32 bytes,
/// the MPT hash is the item. Otherwise, the MPT hash is the
/// Keccak-256 hash of the item.
/// The easiest way to compare variable-length byte sequences is
/// to compare their Keccak-256 hashes.
/// @param item The RLP item to be hashed.
/// @return Keccak-256(MPT-hash(item))
function _mptHashHash(
RLPReader.RLPItem memory item
) private pure returns (bytes32) {
if (item.len < 32) {
return item.rlpBytesKeccak256();
} else {
return keccak256(abi.encodePacked(item.rlpBytesKeccak256()));
}
}
function _isEmptyBytesequence(
RLPReader.RLPItem memory item
) private pure returns (bool) {
if (item.len != 1) {
return false;
}
uint8 b;
uint256 memPtr = item.memPtr;
assembly {
b := byte(0, mload(memPtr))
}
return b == 0x80 /* empty byte string */;
}
function _merklePatriciaCompactDecode(
bytes memory compact
) private pure returns (bool isLeaf, bytes memory nibbles) {
require(compact.length > 0);
uint256 first_nibble = (uint8(compact[0]) >> 4) & 0xF;
uint256 skipNibbles;
if (first_nibble == 0) {
skipNibbles = 2;
isLeaf = false;
} else if (first_nibble == 1) {
skipNibbles = 1;
isLeaf = false;
} else if (first_nibble == 2) {
skipNibbles = 2;
isLeaf = true;
} else if (first_nibble == 3) {
skipNibbles = 1;
isLeaf = true;
} else {
// Not supposed to happen!
revert();
}
return (isLeaf, _decodeNibbles(compact, skipNibbles));
}
function _decodeNibbles(
bytes memory compact,
uint256 skipNibbles
) private pure returns (bytes memory nibbles) {
require(compact.length > 0);
uint256 length = compact.length * 2;
require(skipNibbles <= length);
length -= skipNibbles;
nibbles = new bytes(length);
uint256 nibblesLength = 0;
for (uint256 i = skipNibbles; i < skipNibbles + length; i += 1) {
if (i % 2 == 0) {
nibbles[nibblesLength] = bytes1((uint8(compact[i / 2]) >> 4) & 0xF);
} else {
nibbles[nibblesLength] = bytes1((uint8(compact[i / 2]) >> 0) & 0xF);
}
nibblesLength += 1;
}
assert(nibblesLength == nibbles.length);
}
function _sharedPrefixLength(
uint256 xsOffset,
bytes memory xs,
bytes memory ys
) private pure returns (uint256) {
uint256 i;
for (i = 0; i + xsOffset < xs.length && i < ys.length; i++) {
if (xs[i + xsOffset] != ys[i]) {
return i;
}
}
return i;
}
}// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import {StateProofVerifier} from '../libs/StateProofVerifier.sol';
/**
* @title IDataWarehouse
* @author BGD Labs
* @notice interface containing the methods definitions of the DataWarehouse contract
*/
interface IDataWarehouse {
/**
* @notice event emitted when a storage root has been processed successfully
* @param caller address that called the processStorageRoot method
* @param account address where the root is generated
* @param blockHash hash of the block where the root was generated
*/
event StorageRootProcessed(
address indexed caller,
address indexed account,
bytes32 indexed blockHash
);
/**
* @notice event emitted when a storage root has been processed successfully
* @param caller address that called the processStorageSlot method
* @param account address where the slot is processed
* @param blockHash hash of the block where the storage proof was generated
* @param slot storage location to search
* @param value storage information on the specified location
*/
event StorageSlotProcessed(
address indexed caller,
address indexed account,
bytes32 indexed blockHash,
bytes32 slot,
uint256 value
);
/**
* @notice method to get the storage roots of an account (token) in a certain block hash
* @param account address of the token to get the storage roots from
* @param blockHash hash of the block from where the roots are generated
* @return state root hash of the account on the block hash specified
*/
function getStorageRoots(
address account,
bytes32 blockHash
) external view returns (bytes32);
/**
* @notice method to process the storage root from an account on a block hash.
* @param account address of the token to get the storage roots from
* @param blockHash hash of the block from where the roots are generated
* @param blockHeaderRLP rlp encoded block header. At same block where the block hash was taken
* @param accountStateProofRLP rlp encoded account state proof, taken in same block as block hash
* @return the storage root
*/
function processStorageRoot(
address account,
bytes32 blockHash,
bytes memory blockHeaderRLP,
bytes memory accountStateProofRLP
) external returns (bytes32);
/**
* @notice method to get the storage value at a certain slot and block hash for a certain address
* @param account address of the token to get the storage roots from
* @param blockHash hash of the block from where the roots are generated
* @param slot hash of the explicit storage placement where the value to get is found.
* @param storageProof generated proof containing the storage, at block hash
* @return an object containing the slot value at the specified storage slot
*/
function getStorage(
address account,
bytes32 blockHash,
bytes32 slot,
bytes memory storageProof
) external view returns (StateProofVerifier.SlotValue memory);
/**
* @notice method to register the storage value at a certain slot and block hash for a certain address
* @param account address of the token to get the storage roots from
* @param blockHash hash of the block from where the roots are generated
* @param slot hash of the explicit storage placement where the value to get is found.
* @param storageProof generated proof containing the storage, at block hash
*/
function processStorageSlot(
address account,
bytes32 blockHash,
bytes32 slot,
bytes calldata storageProof
) external;
/**
* @notice method to get the value from storage at a certain block hash, previously registered.
* @param blockHash hash of the block from where the roots are generated
* @param account address of the token to get the storage roots from
* @param slot hash of the explicit storage placement where the value to get is found.
* @return numeric slot value of the slot. The value must be decoded to get the actual stored information
*/
function getRegisteredSlot(
bytes32 blockHash,
address account,
bytes32 slot
) external view returns (uint256);
}{
"remappings": [
"aave-delivery-infrastructure/=lib/adi-deploy/lib/aave-delivery-infrastructure/src/",
"solidity-utils/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/src/",
"forge-std/=lib/adi-deploy/lib/aave-helpers/lib/forge-std/src/",
"openzeppelin-contracts/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/",
"aave-helpers/=lib/adi-deploy/lib/aave-helpers/src/",
"aave-address-book/=lib/adi-deploy/lib/aave-helpers/lib/aave-address-book/src/",
"aave-v3-origin/=lib/adi-deploy/lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/src/",
"adi-deploy/=lib/adi-deploy/",
"@openzeppelin/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/openzeppelin-contracts/",
"@openzeppelin/contracts-upgradeable/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
"aave-v3-origin-tests/=lib/adi-deploy/lib/aave-helpers/lib/aave-address-book/lib/aave-v3-origin/tests/",
"adi-scripts/=lib/adi-deploy/lib/aave-delivery-infrastructure/scripts/",
"adi-tests/=lib/adi-deploy/lib/aave-delivery-infrastructure/tests/",
"adi/=lib/adi-deploy/lib/aave-delivery-infrastructure/src/contracts/",
"ds-test/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"halmos-cheatcodes/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
"hyperlane-monorepo/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/hyperlane-monorepo/solidity/contracts/",
"openzeppelin-contracts-upgradeable/=lib/adi-deploy/lib/aave-delivery-infrastructure/lib/solidity-utils/lib/openzeppelin-contracts-upgradeable/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "shanghai",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"dataWarehouse","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint128[]","name":"storageSlots","type":"uint128[]"}],"name":"VotingAssetAdd","type":"event"},{"inputs":[],"name":"AAVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"A_AAVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"A_AAVE_BASE_BALANCE_SLOT","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"A_AAVE_DELEGATED_STATE_SLOT","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_BALANCE_SLOT","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DATA_WAREHOUSE","outputs":[{"internalType":"contract IDataWarehouse","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POWER_SCALE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STK_AAVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"STK_AAVE_SLASHING_EXCHANGE_RATE_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STK_AAVE_SLASHING_EXCHANGE_RATE_SLOT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getVotingAssetConfig","outputs":[{"components":[{"internalType":"uint128[]","name":"storageSlots","type":"uint128[]"}],"internalType":"struct IBaseVotingStrategy.VotingAssetConfig","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getVotingAssetList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint128","name":"storageSlot","type":"uint128"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"}],"name":"getVotingPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"blockHash","type":"bytes32"}],"name":"hasRequiredRoots","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint128","name":"slot","type":"uint128"}],"name":"isTokenSlotAccepted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
60a060405234801562000010575f80fd5b506040516200157b3803806200157b8339810160408190526200003391620005b7565b5f6200003e62000341565b8051604080518082019091526002815261313560f01b6020820152919250620000855760405162461bcd60e51b81526004016200007c9190620005e6565b60405180910390fd5b505f5b8151811015620002e9575f620000a082600162000634565b90505b82518110156200014157828181518110620000c257620000c262000654565b60200260200101516001600160a01b0316838381518110620000e857620000e862000654565b60200260200101516001600160a01b031614156040518060400160405280600281526020016106e760f31b81525090620001375760405162461bcd60e51b81526004016200007c9190620005e6565b50600101620000a3565b505f620001708383815181106200015c576200015c62000654565b60200260200101516200044160201b60201c565b805151604080518082019091526002815261373960f01b6020820152919250620001af5760405162461bcd60e51b81526004016200007c9190620005e6565b505f5b8151518110156200027c575f620001cb82600162000634565b90505b82515181101562000272578251805182908110620001f057620001f062000654565b60200260200101516001600160801b0316835f0151838151811062000219576200021962000654565b60200260200101516001600160801b0316141560405180604001604052806002815260200161038360f41b81525090620002685760405162461bcd60e51b81526004016200007c9190620005e6565b50600101620001ce565b50600101620001b2565b5082828151811062000292576200029262000654565b60200260200101516001600160a01b03167fbe5e9292af59bc473a1eb54ed4b2a5bca33735ed12f2752005753b62027a02ca825f0151604051620002d7919062000668565b60405180910390a25060010162000088565b505060408051808201909152600281526106c760f31b60208201526001600160a01b0382166200032e5760405162461bcd60e51b81526004016200007c9190620005e6565b506001600160a01b0316608052620006b6565b604080516003808252608082019092526060915f9190602082018480368337019050509050737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9815f8151811062000390576200039062000654565b6001600160a01b0390921660209283029190910190910152620003c4734da27a545c0c5b758a6ba100e3a049001de870f590565b81600181518110620003da57620003da62000654565b6001600160a01b03909216602092830291909101909101526200040e73a700b4eb416be35b2911fd5dee80678ff64ff6c990565b8160028151811062000424576200042462000654565b6001600160a01b0390921660209283029190910190910152919050565b6040805160208101909152606081526040805160208101909152606081526200047b737fc66500c84a76ad7e9c93437bfc5ac33e2ddae990565b6001600160a01b0316836001600160a01b03161480620004b757506001600160a01b038316734da27a545c0c5b758a6ba100e3a049001de870f5145b156200051957604080516001808252818301909252906020808301908036833750505080825280515f91908290620004f357620004f362000654565b60200260200101906001600160801b031690816001600160801b031681525050620005b1565b73a700b4eb416be35b2911fd5dee80678ff64ff6c8196001600160a01b03841601620005b15760408051600280825260608201835290916020830190803683375050508082528051603491905f9062000576576200057662000654565b60200260200101906001600160801b031690816001600160801b0316815250506040815f0151600181518110620004f357620004f362000654565b92915050565b5f60208284031215620005c8575f80fd5b81516001600160a01b0381168114620005df575f80fd5b9392505050565b5f602080835283518060208501525f5b818110156200061457858101830151858201604001528201620005f6565b505f604082860101526040601f19601f8301168501019250505092915050565b80820180821115620005b157634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b602080825282518282018190525f9190848201906040850190845b81811015620006aa5783516001600160801b03168352928401929184019160010162000683565b50909695505050505050565b608051610e89620006f25f395f8181610240015281816102c6015281816108510152818161094801528181610a360152610b2c0152610e895ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c806365d5fbeb11610093578063bdf2878d11610063578063bdf2878d146101f2578063be0d56d81461020c578063c3533db214610221578063de6bd0821461023b575f80fd5b806365d5fbeb146101ad57806369098bd7146101b5578063840261c5146101ca578063ac5af54b146101ea575f80fd5b806337dde417116100ce57806337dde4171461014157806340cd3d3f1461016457806348ccda3c14610173578063570a9714146101a1575f80fd5b80630c5fc74b146100f45780632a71f9531461011957806335f2a5c41461013a575b5f80fd5b6100fc604081565b6040516001600160801b0390911681526020015b60405180910390f35b61012c610127366004610c49565b610262565b604051908152602001610110565b6100fc5f81565b61015461014f366004610c88565b6105a8565b6040519015158152602001610110565b61012c670de0b6b3a764000081565b737fc66500c84a76ad7e9c93437bfc5ac33e2ddae95b6040516001600160a01b039091168152602001610110565b61012c6402540be40081565b61012c605181565b6101bd610614565b6040516101109190610cb9565b6101dd6101d8366004610d05565b6106fd565b6040516101109190610d25565b6100fc603481565b734da27a545c0c5b758a6ba100e3a049001de870f5610189565b61021f61021a366004610d7d565b61084e565b005b73a700b4eb416be35b2911fd5dee80678ff64ff6c9610189565b6101897f000000000000000000000000000000000000000000000000000000000000000081565b5f80734da27a545c0c5b758a6ba100e3a049001de870f4196001600160a01b038716016103f3576001600160801b0385166103ee576040516302f36c3b60e61b8152600481018490526001600160a01b038781166024830152605160448301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063bcdb0ec090606401602060405180830381865afa15801561030d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103319190610d94565b90506001600160d81b03811661035b6402540be40068ffffffffffffffffff60b089901c16610dbf565b92505f60f887901c600381111561037457610374610dd6565b9050600181600381111561038a5761038a610dd6565b141580156103aa575060038160038111156103a7576103a7610dd6565b14155b156103cb576103c86cffffffffffffffffffffffffff881685610dea565b93505b816103de670de0b6b3a764000086610dbf565b6103e89190610dfd565b93505050505b61059f565b737fc66500c84a76ad7e9c93437bfc5ac33e2ddae8196001600160a01b038716016104ba576001600160801b0385166103ee576104446402540be40068ffffffffffffffffff60b087901c16610dbf565b90505f60f885901c600381111561045d5761045d610dd6565b9050600181600381111561047357610473610dd6565b141580156104935750600381600381111561049057610490610dd6565b14155b156104b4576104b16cffffffffffffffffffffffffff861683610dea565b91505b5061059f565b73a700b4eb416be35b2911fd5dee80678ff64ff6c8196001600160a01b0387160161059f57603f196001600160801b038616016105165761050f6402540be40068ffffffffffffffffff604887901c16610dbf565b905061059f565b6033196001600160801b0386160161059f576effffffffffffffffffffffffffffff84165f60ff607887901c16600381111561055457610554610dd6565b9050600181600381111561056a5761056a610dd6565b1415801561058a5750600381600381111561058757610587610dd6565b14155b1561059c576105998284610dea565b92505b50505b95945050505050565b5f806105b3846106fd565b90505f5b8151518110156106085781518051829081106105d5576105d5610e1c565b60200260200101516001600160801b0316846001600160801b0316036106005760019250505061060e565b6001016105b7565b505f9150505b92915050565b604080516003808252608082019092526060915f9190602082018480368337019050509050737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9815f8151811061066057610660610e1c565b6001600160a01b0390921660209283029190910190910152734da27a545c0c5b758a6ba100e3a049001de870f5816001815181106106a0576106a0610e1c565b6001600160a01b039092166020928302919091019091015273a700b4eb416be35b2911fd5dee80678ff64ff6c9816002815181106106e0576106e0610e1c565b6001600160a01b0390921660209283029190910190910152919050565b604080516020808201835260608083528351918201909352918252906001600160a01b038316737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9148061076057506001600160a01b038316734da27a545c0c5b758a6ba100e3a049001de870f5145b156107bd57604080516001808252818301909252906020808301908036833750505080825280515f9190829061079857610798610e1c565b60200260200101906001600160801b031690816001600160801b03168152505061060e565b73a700b4eb416be35b2911fd5dee80678ff64ff6c8196001600160a01b0384160161060e5760408051600280825260608201835290916020830190803683375050508082528051603491905f9061081657610816610e1c565b60200260200101906001600160801b031690816001600160801b0316815250506040815f015160018151811061079857610798610e1c565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166381ac42b5737fc66500c84a76ad7e9c93437bfc5ac33e2ddae96040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381865afa1580156108dc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109009190610d94565b1415604051806040016040528060028152602001610c8d60f21b815250906109445760405162461bcd60e51b815260040161093b9190610e30565b60405180910390fd5b505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166381ac42b5734da27a545c0c5b758a6ba100e3a049001de870f56040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381865afa1580156109d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f79190610d94565b141560405180604001604052806002815260200161323560f01b81525090610a325760405162461bcd60e51b815260040161093b9190610e30565b505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166381ac42b573a700b4eb416be35b2911fd5dee80678ff64ff6c96040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381865afa158015610ac1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae59190610d94565b141560405180604001604052806002815260200161333760f01b81525090610b205760405162461bcd60e51b815260040161093b9190610e30565b505f6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663bcdb0ec083734da27a545c0c5b758a6ba100e3a049001de870f560405160e084901b6001600160e01b031916815260048101929092526001600160a01b0316602482015260516044820152606401602060405180830381865afa158015610bb6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bda9190610d94565b1160405180604001604052806002815260200161191b60f11b81525090610c145760405162461bcd60e51b815260040161093b9190610e30565b5050565b80356001600160a01b0381168114610c2e575f80fd5b919050565b80356001600160801b0381168114610c2e575f80fd5b5f805f8060808587031215610c5c575f80fd5b610c6585610c18565b9350610c7360208601610c33565b93969395505050506040820135916060013590565b5f8060408385031215610c99575f80fd5b610ca283610c18565b9150610cb060208401610c33565b90509250929050565b602080825282518282018190525f9190848201906040850190845b81811015610cf95783516001600160a01b031683529284019291840191600101610cd4565b50909695505050505050565b5f60208284031215610d15575f80fd5b610d1e82610c18565b9392505050565b602080825282518282018290528051604084018190525f9291820190839060608601905b80831015610d725783516001600160801b03168252928401926001929092019190840190610d49565b509695505050505050565b5f60208284031215610d8d575f80fd5b5035919050565b5f60208284031215610da4575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761060e5761060e610dab565b634e487b7160e01b5f52602160045260245ffd5b8082018082111561060e5761060e610dab565b5f82610e1757634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b5f602080835283518060208501525f5b81811015610e5c57858101830151858201604001528201610e40565b505f604082860101526040601f19601f830116850101925050509291505056fea164736f6c6343000816000a000000000000000000000000a638c14525caee8e498a67b409ccb1b7b34c3981
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106100f0575f3560e01c806365d5fbeb11610093578063bdf2878d11610063578063bdf2878d146101f2578063be0d56d81461020c578063c3533db214610221578063de6bd0821461023b575f80fd5b806365d5fbeb146101ad57806369098bd7146101b5578063840261c5146101ca578063ac5af54b146101ea575f80fd5b806337dde417116100ce57806337dde4171461014157806340cd3d3f1461016457806348ccda3c14610173578063570a9714146101a1575f80fd5b80630c5fc74b146100f45780632a71f9531461011957806335f2a5c41461013a575b5f80fd5b6100fc604081565b6040516001600160801b0390911681526020015b60405180910390f35b61012c610127366004610c49565b610262565b604051908152602001610110565b6100fc5f81565b61015461014f366004610c88565b6105a8565b6040519015158152602001610110565b61012c670de0b6b3a764000081565b737fc66500c84a76ad7e9c93437bfc5ac33e2ddae95b6040516001600160a01b039091168152602001610110565b61012c6402540be40081565b61012c605181565b6101bd610614565b6040516101109190610cb9565b6101dd6101d8366004610d05565b6106fd565b6040516101109190610d25565b6100fc603481565b734da27a545c0c5b758a6ba100e3a049001de870f5610189565b61021f61021a366004610d7d565b61084e565b005b73a700b4eb416be35b2911fd5dee80678ff64ff6c9610189565b6101897f000000000000000000000000a638c14525caee8e498a67b409ccb1b7b34c398181565b5f80734da27a545c0c5b758a6ba100e3a049001de870f4196001600160a01b038716016103f3576001600160801b0385166103ee576040516302f36c3b60e61b8152600481018490526001600160a01b038781166024830152605160448301525f917f000000000000000000000000a638c14525caee8e498a67b409ccb1b7b34c39819091169063bcdb0ec090606401602060405180830381865afa15801561030d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103319190610d94565b90506001600160d81b03811661035b6402540be40068ffffffffffffffffff60b089901c16610dbf565b92505f60f887901c600381111561037457610374610dd6565b9050600181600381111561038a5761038a610dd6565b141580156103aa575060038160038111156103a7576103a7610dd6565b14155b156103cb576103c86cffffffffffffffffffffffffff881685610dea565b93505b816103de670de0b6b3a764000086610dbf565b6103e89190610dfd565b93505050505b61059f565b737fc66500c84a76ad7e9c93437bfc5ac33e2ddae8196001600160a01b038716016104ba576001600160801b0385166103ee576104446402540be40068ffffffffffffffffff60b087901c16610dbf565b90505f60f885901c600381111561045d5761045d610dd6565b9050600181600381111561047357610473610dd6565b141580156104935750600381600381111561049057610490610dd6565b14155b156104b4576104b16cffffffffffffffffffffffffff861683610dea565b91505b5061059f565b73a700b4eb416be35b2911fd5dee80678ff64ff6c8196001600160a01b0387160161059f57603f196001600160801b038616016105165761050f6402540be40068ffffffffffffffffff604887901c16610dbf565b905061059f565b6033196001600160801b0386160161059f576effffffffffffffffffffffffffffff84165f60ff607887901c16600381111561055457610554610dd6565b9050600181600381111561056a5761056a610dd6565b1415801561058a5750600381600381111561058757610587610dd6565b14155b1561059c576105998284610dea565b92505b50505b95945050505050565b5f806105b3846106fd565b90505f5b8151518110156106085781518051829081106105d5576105d5610e1c565b60200260200101516001600160801b0316846001600160801b0316036106005760019250505061060e565b6001016105b7565b505f9150505b92915050565b604080516003808252608082019092526060915f9190602082018480368337019050509050737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9815f8151811061066057610660610e1c565b6001600160a01b0390921660209283029190910190910152734da27a545c0c5b758a6ba100e3a049001de870f5816001815181106106a0576106a0610e1c565b6001600160a01b039092166020928302919091019091015273a700b4eb416be35b2911fd5dee80678ff64ff6c9816002815181106106e0576106e0610e1c565b6001600160a01b0390921660209283029190910190910152919050565b604080516020808201835260608083528351918201909352918252906001600160a01b038316737fc66500c84a76ad7e9c93437bfc5ac33e2ddae9148061076057506001600160a01b038316734da27a545c0c5b758a6ba100e3a049001de870f5145b156107bd57604080516001808252818301909252906020808301908036833750505080825280515f9190829061079857610798610e1c565b60200260200101906001600160801b031690816001600160801b03168152505061060e565b73a700b4eb416be35b2911fd5dee80678ff64ff6c8196001600160a01b0384160161060e5760408051600280825260608201835290916020830190803683375050508082528051603491905f9061081657610816610e1c565b60200260200101906001600160801b031690816001600160801b0316815250506040815f015160018151811061079857610798610e1c565b5f7f000000000000000000000000a638c14525caee8e498a67b409ccb1b7b34c39816001600160a01b03166381ac42b5737fc66500c84a76ad7e9c93437bfc5ac33e2ddae96040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381865afa1580156108dc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109009190610d94565b1415604051806040016040528060028152602001610c8d60f21b815250906109445760405162461bcd60e51b815260040161093b9190610e30565b60405180910390fd5b505f7f000000000000000000000000a638c14525caee8e498a67b409ccb1b7b34c39816001600160a01b03166381ac42b5734da27a545c0c5b758a6ba100e3a049001de870f56040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381865afa1580156109d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f79190610d94565b141560405180604001604052806002815260200161323560f01b81525090610a325760405162461bcd60e51b815260040161093b9190610e30565b505f7f000000000000000000000000a638c14525caee8e498a67b409ccb1b7b34c39816001600160a01b03166381ac42b573a700b4eb416be35b2911fd5dee80678ff64ff6c96040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401602060405180830381865afa158015610ac1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae59190610d94565b141560405180604001604052806002815260200161333760f01b81525090610b205760405162461bcd60e51b815260040161093b9190610e30565b505f6001600160a01b037f000000000000000000000000a638c14525caee8e498a67b409ccb1b7b34c39811663bcdb0ec083734da27a545c0c5b758a6ba100e3a049001de870f560405160e084901b6001600160e01b031916815260048101929092526001600160a01b0316602482015260516044820152606401602060405180830381865afa158015610bb6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bda9190610d94565b1160405180604001604052806002815260200161191b60f11b81525090610c145760405162461bcd60e51b815260040161093b9190610e30565b5050565b80356001600160a01b0381168114610c2e575f80fd5b919050565b80356001600160801b0381168114610c2e575f80fd5b5f805f8060808587031215610c5c575f80fd5b610c6585610c18565b9350610c7360208601610c33565b93969395505050506040820135916060013590565b5f8060408385031215610c99575f80fd5b610ca283610c18565b9150610cb060208401610c33565b90509250929050565b602080825282518282018190525f9190848201906040850190845b81811015610cf95783516001600160a01b031683529284019291840191600101610cd4565b50909695505050505050565b5f60208284031215610d15575f80fd5b610d1e82610c18565b9392505050565b602080825282518282018290528051604084018190525f9291820190839060608601905b80831015610d725783516001600160801b03168252928401926001929092019190840190610d49565b509695505050505050565b5f60208284031215610d8d575f80fd5b5035919050565b5f60208284031215610da4575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761060e5761060e610dab565b634e487b7160e01b5f52602160045260245ffd5b8082018082111561060e5761060e610dab565b5f82610e1757634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b5f602080835283518060208501525f5b81811015610e5c57858101830151858201604001528201610e40565b505f604082860101526040601f19601f830116850101925050509291505056fea164736f6c6343000816000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a638c14525caee8e498a67b409ccb1b7b34c3981
-----Decoded View---------------
Arg [0] : dataWarehouse (address): 0xa638c14525CAEE8e498A67b409CCb1B7b34c3981
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000a638c14525caee8e498a67b409ccb1b7b34c3981
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.