ETH Price: $2,608.36 (+5.32%)
Gas: 6.62 Gwei

Transaction Decoder

Block:
21729103 at Jan-29-2025 08:50:35 AM +UTC
Transaction Fee:
0.000188573702336379 ETH $0.49
Gas Used:
77,967 Gas / 2.418634837 Gwei

Emitted Events:

68 EternalStorageProxy.0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0( 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0, 0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000030fb61178f39c0452ced4ad9a7fec3344cb10b2e )

Account State Difference:

  Address   Before After State Difference Code
0x30Fb6117...44CB10B2E
(Gnosis Bridge: Deployer)
0.004832532549667315 Eth
Nonce: 32
0.004643958847330936 Eth
Nonce: 33
0.000188573702336379
(Titan Builder)
7.634825134720116222 Eth7.634864118220116222 Eth0.0000389835
0x9acCFAD7...d1d5547BD

Execution Trace

EternalStorageProxy.c4d66de8( )
  • HashiManager.initialize( _owner=0x30Fb61178F39c0452cED4AD9A7FEC3344CB10B2E ) => ( True )
    • EternalStorageProxy.upgradeabilityOwner( ) => ( 0x30Fb61178F39c0452cED4AD9A7FEC3344CB10B2E )
    • EternalStorageProxy.CALL( )
      File 1 of 2: EternalStorageProxy
      pragma solidity ^0.4.24;
      /**
       * Utility library of inline functions on addresses
       */
      library AddressUtils {
        /**
         * Returns whether the target address is a contract
         * @dev This function will return false if invoked during the constructor of a contract,
         * as the code is not actually created until after the constructor finishes.
         * @param _addr address to check
         * @return whether the target address is a contract
         */
        function isContract(address _addr) internal view returns (bool) {
          uint256 size;
          // XXX Currently there is no better way to check if there is a contract in an address
          // than to check the size of the code at that address.
          // See https://ethereum.stackexchange.com/a/14016/36603
          // for more details about how this works.
          // TODO Check this again before the Serenity release, because all addresses will be
          // contracts then.
          // solium-disable-next-line security/no-inline-assembly
          assembly { size := extcodesize(_addr) }
          return size > 0;
        }
      }
      pragma solidity 0.4.24;
      /**
       * @title EternalStorage
       * @dev This contract holds all the necessary state variables to carry out the storage of any contract.
       */
      contract EternalStorage {
          mapping(bytes32 => uint256) internal uintStorage;
          mapping(bytes32 => string) internal stringStorage;
          mapping(bytes32 => address) internal addressStorage;
          mapping(bytes32 => bytes) internal bytesStorage;
          mapping(bytes32 => bool) internal boolStorage;
          mapping(bytes32 => int256) internal intStorage;
      }
      pragma solidity 0.4.24;
      import "./EternalStorage.sol";
      import "./OwnedUpgradeabilityProxy.sol";
      /**
       * @title EternalStorageProxy
       * @dev This proxy holds the storage of the token contract and delegates every call to the current implementation set.
       * Besides, it allows to upgrade the token's behaviour towards further implementations, and provides basic
       * authorization control functionalities
       */
      // solhint-disable-next-line no-empty-blocks
      contract EternalStorageProxy is EternalStorage, OwnedUpgradeabilityProxy {}
      pragma solidity 0.4.24;
      import "./UpgradeabilityProxy.sol";
      import "./UpgradeabilityOwnerStorage.sol";
      /**
       * @title OwnedUpgradeabilityProxy
       * @dev This contract combines an upgradeability proxy with basic authorization control functionalities
       */
      contract OwnedUpgradeabilityProxy is UpgradeabilityOwnerStorage, UpgradeabilityProxy {
          /**
          * @dev Event to show ownership has been transferred
          * @param previousOwner representing the address of the previous owner
          * @param newOwner representing the address of the new owner
          */
          event ProxyOwnershipTransferred(address previousOwner, address newOwner);
          /**
          * @dev the constructor sets the original owner of the contract to the sender account.
          */
          constructor() public {
              setUpgradeabilityOwner(msg.sender);
          }
          /**
          * @dev Throws if called by any account other than the owner.
          */
          modifier onlyUpgradeabilityOwner() {
              require(msg.sender == upgradeabilityOwner());
              /* solcov ignore next */
              _;
          }
          /**
          * @dev Allows the current owner to transfer control of the contract to a newOwner.
          * @param newOwner The address to transfer ownership to.
          */
          function transferProxyOwnership(address newOwner) external onlyUpgradeabilityOwner {
              require(newOwner != address(0));
              emit ProxyOwnershipTransferred(upgradeabilityOwner(), newOwner);
              setUpgradeabilityOwner(newOwner);
          }
          /**
          * @dev Allows the upgradeability owner to upgrade the current version of the proxy.
          * @param version representing the version name of the new implementation to be set.
          * @param implementation representing the address of the new implementation to be set.
          */
          function upgradeTo(uint256 version, address implementation) public onlyUpgradeabilityOwner {
              _upgradeTo(version, implementation);
          }
          /**
          * @dev Allows the upgradeability owner to upgrade the current version of the proxy and call the new implementation
          * to initialize whatever is needed through a low level call.
          * @param version representing the version name of the new implementation to be set.
          * @param implementation representing the address of the new implementation to be set.
          * @param data represents the msg.data to bet sent in the low level call. This parameter may include the function
          * signature of the implementation to be called with the needed payload
          */
          function upgradeToAndCall(uint256 version, address implementation, bytes data)
              external
              payable
              onlyUpgradeabilityOwner
          {
              upgradeTo(version, implementation);
              // solhint-disable-next-line avoid-call-value
              require(address(this).call.value(msg.value)(data));
          }
      }
      pragma solidity 0.4.24;
      /**
       * @title Proxy
       * @dev Gives the possibility to delegate any call to a foreign implementation.
       */
      contract Proxy {
          /**
          * @dev Tells the address of the implementation where every call will be delegated.
          * @return address of the implementation to which it will be delegated
          */
          /* solcov ignore next */
          function implementation() public view returns (address);
          /**
          * @dev Fallback function allowing to perform a delegatecall to the given implementation.
          * This function will return whatever the implementation call returns
          */
          function() public payable {
              // solhint-disable-previous-line no-complex-fallback
              address _impl = implementation();
              require(_impl != address(0));
              assembly {
                  /*
                      0x40 is the "free memory slot", meaning a pointer to next slot of empty memory. mload(0x40)
                      loads the data in the free memory slot, so `ptr` is a pointer to the next slot of empty
                      memory. It's needed because we're going to write the return data of delegatecall to the
                      free memory slot.
                  */
                  let ptr := mload(0x40)
                  /*
                      `calldatacopy` is copy calldatasize bytes from calldata
                      First argument is the destination to which data is copied(ptr)
                      Second argument specifies the start position of the copied data.
                          Since calldata is sort of its own unique location in memory,
                          0 doesn't refer to 0 in memory or 0 in storage - it just refers to the zeroth byte of calldata.
                          That's always going to be the zeroth byte of the function selector.
                      Third argument, calldatasize, specifies how much data will be copied.
                          calldata is naturally calldatasize bytes long (same thing as msg.data.length)
                  */
                  calldatacopy(ptr, 0, calldatasize)
                  /*
                      delegatecall params explained:
                      gas: the amount of gas to provide for the call. `gas` is an Opcode that gives
                          us the amount of gas still available to execution
                      _impl: address of the contract to delegate to
                      ptr: to pass copied data
                      calldatasize: loads the size of `bytes memory data`, same as msg.data.length
                      0, 0: These are for the `out` and `outsize` params. Because the output could be dynamic,
                              these are set to 0, 0 so the output data will not be written to memory. The output
                              data will be read using `returndatasize` and `returdatacopy` instead.
                      result: This will be 0 if the call fails and 1 if it succeeds
                  */
                  let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
                  /*
                  */
                  /*
                      ptr current points to the value stored at 0x40,
                      because we assigned it like ptr := mload(0x40).
                      Because we use 0x40 as a free memory pointer,
                      we want to make sure that the next time we want to allocate memory,
                      we aren't overwriting anything important.
                      So, by adding ptr and returndatasize,
                      we get a memory location beyond the end of the data we will be copying to ptr.
                      We place this in at 0x40, and any reads from 0x40 will now read from free memory
                  */
                  mstore(0x40, add(ptr, returndatasize))
                  /*
                      `returndatacopy` is an Opcode that copies the last return data to a slot. `ptr` is the
                          slot it will copy to, 0 means copy from the beginning of the return data, and size is
                          the amount of data to copy.
                      `returndatasize` is an Opcode that gives us the size of the last return data. In this case, that is the size of the data returned from delegatecall
                  */
                  returndatacopy(ptr, 0, returndatasize)
                  /*
                      if `result` is 0, revert.
                      if `result` is 1, return `size` amount of data from `ptr`. This is the data that was
                      copied to `ptr` from the delegatecall return data
                  */
                  switch result
                      case 0 {
                          revert(ptr, returndatasize)
                      }
                      default {
                          return(ptr, returndatasize)
                      }
              }
          }
      }
      pragma solidity 0.4.24;
      /**
       * @title UpgradeabilityOwnerStorage
       * @dev This contract keeps track of the upgradeability owner
       */
      contract UpgradeabilityOwnerStorage {
          // Owner of the contract
          address internal _upgradeabilityOwner;
          /**
          * @dev Tells the address of the owner
          * @return the address of the owner
          */
          function upgradeabilityOwner() public view returns (address) {
              return _upgradeabilityOwner;
          }
          /**
          * @dev Sets the address of the owner
          */
          function setUpgradeabilityOwner(address newUpgradeabilityOwner) internal {
              _upgradeabilityOwner = newUpgradeabilityOwner;
          }
      }
      pragma solidity 0.4.24;
      import "openzeppelin-solidity/contracts/AddressUtils.sol";
      import "./Proxy.sol";
      import "./UpgradeabilityStorage.sol";
      /**
       * @title UpgradeabilityProxy
       * @dev This contract represents a proxy where the implementation address to which it will delegate can be upgraded
       */
      contract UpgradeabilityProxy is Proxy, UpgradeabilityStorage {
          /**
          * @dev This event will be emitted every time the implementation gets upgraded
          * @param version representing the version name of the upgraded implementation
          * @param implementation representing the address of the upgraded implementation
          */
          event Upgraded(uint256 version, address indexed implementation);
          /**
          * @dev Upgrades the implementation address
          * @param version representing the version name of the new implementation to be set
          * @param implementation representing the address of the new implementation to be set
          */
          function _upgradeTo(uint256 version, address implementation) internal {
              require(_implementation != implementation);
              // This additional check verifies that provided implementation is at least a contract
              require(AddressUtils.isContract(implementation));
              // This additional check guarantees that new version will be at least greater than the privios one,
              // so it is impossible to reuse old versions, or use the last version twice
              require(version > _version);
              _version = version;
              _implementation = implementation;
              emit Upgraded(version, implementation);
          }
      }
      pragma solidity 0.4.24;
      /**
       * @title UpgradeabilityStorage
       * @dev This contract holds all the necessary state variables to support the upgrade functionality
       */
      contract UpgradeabilityStorage {
          // Version name of the current implementation
          uint256 internal _version;
          // Address of the current implementation
          address internal _implementation;
          /**
          * @dev Tells the version name of the current implementation
          * @return uint256 representing the name of the current version
          */
          function version() external view returns (uint256) {
              return _version;
          }
          /**
          * @dev Tells the address of the current implementation
          * @return address of the current implementation
          */
          function implementation() public view returns (address) {
              return _implementation;
          }
      }
      

      File 2 of 2: HashiManager
      pragma solidity ^0.4.24;
      /**
       * @title SafeMath
       * @dev Math operations with safety checks that throw on error
       */
      library SafeMath {
        /**
        * @dev Multiplies two numbers, throws on overflow.
        */
        function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
          // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
          // benefit is lost if 'b' is also tested.
          // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
          if (_a == 0) {
            return 0;
          }
          c = _a * _b;
          assert(c / _a == _b);
          return c;
        }
        /**
        * @dev Integer division of two numbers, truncating the quotient.
        */
        function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
          // assert(_b > 0); // Solidity automatically throws when dividing by 0
          // uint256 c = _a / _b;
          // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold
          return _a / _b;
        }
        /**
        * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
        */
        function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
          assert(_b <= _a);
          return _a - _b;
        }
        /**
        * @dev Adds two numbers, throws on overflow.
        */
        function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
          c = _a + _b;
          assert(c >= _a);
          return c;
        }
      }
      pragma solidity 0.4.24;
      interface IUpgradeabilityOwnerStorage {
          function upgradeabilityOwner() external view returns (address);
      }
      pragma solidity 0.4.24;
      /**
       * @title EternalStorage
       * @dev This contract holds all the necessary state variables to carry out the storage of any contract.
       */
      contract EternalStorage {
          mapping(bytes32 => uint256) internal uintStorage;
          mapping(bytes32 => string) internal stringStorage;
          mapping(bytes32 => address) internal addressStorage;
          mapping(bytes32 => bytes) internal bytesStorage;
          mapping(bytes32 => bool) internal boolStorage;
          mapping(bytes32 => int256) internal intStorage;
      }
      pragma solidity 0.4.24;
      import "./Ownable.sol";
      import "openzeppelin-solidity/contracts/math/SafeMath.sol";
      import "./InitializableBridge.sol";
      contract HashiManager is InitializableBridge, Ownable {
          bytes32 internal constant N_ADAPTERS = 0xdcf7815b28c450099ee39fe328212215e261dd8ce26acdea76caf742d778991e; // keccak256(abi.encodePacked("nAdapters"))
          bytes32 internal constant N_REPORTERS = 0x7759f17e5239c7f5c713a5c2ca4f103cbe6896de01dabfb0d08276642d579e33; // keccak256(abi.encodePacked("nReporters"))
          bytes32 internal constant YAHO = 0xb947d41ce6141eb4dc972fcad3b49fe0eb8d5f59730728c86b8f6e1427912f0e; // keccak256(abi.encodePacked("yaho"))
          bytes32 internal constant YARU = 0x524607f5322f856f1415d60956f8220a13a3abe3281979fdb843027035724c76; // keccak256(abi.encodePacked("yaru"))
          bytes32 internal constant TARGET_ADDRESS = 0x2f1696ba9bd43014bc580768c9270c32ad765cbf97d2a2ba5e81ab9f1ee90561; // keccak256(abi.encodePacked("targetAddress"))
          bytes32 internal constant TARGET_CHAIN_ID = 0xbd2b577e24554caf96874c1f333079c108fe5afbd441f36a76920df41d10820c; // keccak256(abi.encodePacked("targetChainId"))
          bytes32 internal constant THRESHOLD = 0xd46c2b20c7303c2e50535d224276492e8a1eda2a3d7398e0bea254640c1154e7; // keccak256(abi.encodePacked("threshold"))
          bytes32 internal constant EXPECTED_THRESHOLD = 0x8d22a2c372a80e72edabc4af18641f1c8144f8c3c74dce591bace2af2a167b88; // keccak256(abi.encodePacked("expectedThreshold"))
          bytes32 internal constant EXPECTED_ADAPTERS_HASH = 0x21aa67cae9293b939ada82eb9133293e592da66aa847a5596523bd6d2bf2529b; // keccak256(abi.encodePacked("expectedAdapters"))
          function initialize(address _owner) external onlyRelevantSender returns (bool) {
              require(!isInitialized());
              _setOwner(_owner);
              setInitialize();
              return isInitialized();
          }
          function setReportersAdaptersAndThreshold(address[] reporters, address[] adapters, uint256 threshold)
              external
              onlyOwner
          {
              _setArray(N_REPORTERS, "reporters", reporters);
              _setArray(N_ADAPTERS, "adapters", adapters);
              uintStorage[THRESHOLD] = threshold;
          }
          function adapters() external view returns (address[]) {
              return _getArray(N_ADAPTERS, "adapters");
          }
          function reporters() external view returns (address[]) {
              return _getArray(N_REPORTERS, "reporters");
          }
          function expectedAdaptersHash() external view returns (bytes32) {
              return bytes32(uintStorage[EXPECTED_ADAPTERS_HASH]);
          }
          function setExpectedAdaptersHash(address[] adapters_) external onlyOwner {
              uintStorage[EXPECTED_ADAPTERS_HASH] = uint256(keccak256(abi.encodePacked(adapters_)));
          }
          function expectedThreshold() external view returns (uint256) {
              return uintStorage[EXPECTED_THRESHOLD];
          }
          function setExpectedThreshold(uint256 expectedThreshold_) external onlyOwner {
              uintStorage[EXPECTED_THRESHOLD] = expectedThreshold_;
          }
          function yaho() external view returns (address) {
              return addressStorage[YAHO];
          }
          function setYaho(address yaho_) external onlyOwner {
              addressStorage[YAHO] = yaho_;
          }
          function yaru() external view returns (address) {
              return addressStorage[YARU];
          }
          function setYaru(address yaru_) external onlyOwner {
              addressStorage[YARU] = yaru_;
          }
          function targetAddress() external view returns (address) {
              return addressStorage[TARGET_ADDRESS];
          }
          function setTargetAddress(address targetAddress_) external onlyOwner {
              addressStorage[TARGET_ADDRESS] = targetAddress_;
          }
          function targetChainId() external view returns (uint256) {
              return uintStorage[TARGET_CHAIN_ID];
          }
          function setTargetChainId(uint256 targetChainId_) external onlyOwner {
              uintStorage[TARGET_CHAIN_ID] = targetChainId_;
          }
          function threshold() external view returns (uint256) {
              return uintStorage[THRESHOLD];
          }
          function _getArray(bytes32 keyLength, bytes32 key) internal view returns (address[]) {
              uint256 n = uintStorage[keyLength];
              address[] memory values = new address[](n);
              for (uint256 i = 0; i < n; i++) values[i] = addressStorage[keccak256(abi.encodePacked(key, i))];
              return values;
          }
          function _setArray(bytes32 keyLength, bytes32 key, address[] values) internal {
              uint256 n = uintStorage[keyLength];
              for (uint256 i = 0; i < n; i++) delete addressStorage[keccak256(abi.encodePacked(key, i))];
              uintStorage[keyLength] = values.length;
              for (uint256 j = 0; j < values.length; j++) addressStorage[keccak256(abi.encodePacked(key, j))] = values[j];
          }
      }
      pragma solidity 0.4.24;
      import "../upgradeability/EternalStorage.sol";
      contract Initializable is EternalStorage {
          bytes32 internal constant INITIALIZED = 0x0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba; // keccak256(abi.encodePacked("isInitialized"))
          function setInitialize() internal {
              boolStorage[INITIALIZED] = true;
          }
          function isInitialized() public view returns (bool) {
              return boolStorage[INITIALIZED];
          }
      }
      pragma solidity 0.4.24;
      import "./Initializable.sol";
      contract InitializableBridge is Initializable {
          bytes32 internal constant DEPLOYED_AT_BLOCK = 0xb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b0; // keccak256(abi.encodePacked("deployedAtBlock"))
          function deployedAtBlock() external view returns (uint256) {
              return uintStorage[DEPLOYED_AT_BLOCK];
          }
      }
      pragma solidity 0.4.24;
      import "../upgradeability/EternalStorage.sol";
      import "../interfaces/IUpgradeabilityOwnerStorage.sol";
      /**
       * @title Ownable
       * @dev This contract has an owner address providing basic authorization control
       */
      contract Ownable is EternalStorage {
          bytes4 internal constant UPGRADEABILITY_OWNER = 0x6fde8202; // upgradeabilityOwner()
          /**
          * @dev Event to show ownership has been transferred
          * @param previousOwner representing the address of the previous owner
          * @param newOwner representing the address of the new owner
          */
          event OwnershipTransferred(address previousOwner, address newOwner);
          /**
          * @dev Throws if called by any account other than the owner.
          */
          modifier onlyOwner() {
              require(msg.sender == owner());
              /* solcov ignore next */
              _;
          }
          /**
          * @dev Throws if called by any account other than contract itself or owner.
          */
          modifier onlyRelevantSender() {
              // proxy owner if used through proxy, address(0) otherwise
              require(
                  !address(this).call(abi.encodeWithSelector(UPGRADEABILITY_OWNER)) || // covers usage without calling through storage proxy
                      msg.sender == IUpgradeabilityOwnerStorage(this).upgradeabilityOwner() || // covers usage through regular proxy calls
                      msg.sender == address(this) // covers calls through upgradeAndCall proxy method
              );
              /* solcov ignore next */
              _;
          }
          bytes32 internal constant OWNER = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0; // keccak256(abi.encodePacked("owner"))
          /**
          * @dev Tells the address of the owner
          * @return the address of the owner
          */
          function owner() public view returns (address) {
              return addressStorage[OWNER];
          }
          /**
          * @dev Allows the current owner to transfer control of the contract to a newOwner.
          * @param newOwner the address to transfer ownership to.
          */
          function transferOwnership(address newOwner) external onlyOwner {
              _setOwner(newOwner);
          }
          /**
          * @dev Sets a new owner address
          */
          function _setOwner(address newOwner) internal {
              require(newOwner != address(0));
              emit OwnershipTransferred(owner(), newOwner);
              addressStorage[OWNER] = newOwner;
          }
      }