ETH Price: $2,586.55 (-3.74%)
Gas: 0.99 Gwei

Contract

0x37745961af1A34110dbc3c92fa9c64bBDd63FF50
 
Transaction Hash
Method
Block
From
To
Execute180189262023-08-29 7:55:23528 days ago1693295723IN
0x37745961...BDd63FF50
0 ETH0.0011795519.5890846
Execute180189232023-08-29 7:54:47528 days ago1693295687IN
0x37745961...BDd63FF50
0 ETH0.0026708318.716545
Execute180188692023-08-29 7:43:59528 days ago1693295039IN
0x37745961...BDd63FF50
0 ETH0.0038881622.41932896
Execute179328242023-08-17 6:43:23540 days ago1692254603IN
0x37745961...BDd63FF50
0 ETH0.0011669419.38351282
Execute178846722023-08-10 13:05:59547 days ago1691672759IN
0x37745961...BDd63FF50
0 ETH0.0055676533.95616251
Execute173861432023-06-01 13:05:47617 days ago1685624747IN
0x37745961...BDd63FF50
0 ETH0.0066408943.68208407
Execute173861382023-06-01 13:04:47617 days ago1685624687IN
0x37745961...BDd63FF50
0 ETH0.0137528844.48409651
Execute173861062023-06-01 12:58:23617 days ago1685624303IN
0x37745961...BDd63FF50
0 ETH0.0026714234.77919154
Execute172875442023-05-18 16:12:11631 days ago1684426331IN
0x37745961...BDd63FF50
0 ETH0.00688305135.77384102
Execute172875072023-05-18 16:04:35631 days ago1684425875IN
0x37745961...BDd63FF50
0 ETH0.01364252153.13017214
Execute172718212023-05-16 10:57:11633 days ago1684234631IN
0x37745961...BDd63FF50
0 ETH0.0066755548.82645182
Transfer172715152023-05-16 9:55:23633 days ago1684230923IN
0x37745961...BDd63FF50
0.8 ETH0.001130947.69332529
Execute171247252023-04-25 17:21:11654 days ago1682443271IN
0x37745961...BDd63FF50
0 ETH0.0063432739.72489888
Transfer171246722023-04-25 17:10:35654 days ago1682442635IN
0x37745961...BDd63FF50
0.99 ETH0.0017477773.70862119
Execute171246582023-04-25 17:07:35654 days ago1682442455IN
0x37745961...BDd63FF50
0 ETH0.0030041467.31534467
Transfer160963152022-12-02 9:45:59798 days ago1669974359IN
0x37745961...BDd63FF50
0.02345454 ETH0.0002813511.86542713
Transfer160961962022-12-02 9:22:11798 days ago1669972931IN
0x37745961...BDd63FF50
0.01330609 ETH0.0002887112.17609961
Transfer160740822022-11-29 7:13:47801 days ago1669706027IN
0x37745961...BDd63FF50
0.00579211 ETH0.0002830611.93745849
Execute158403092022-10-27 15:29:11834 days ago1666884551IN
0x37745961...BDd63FF50
0 ETH0.0045165222.23627286
Execute158403002022-10-27 15:27:23834 days ago1666884443IN
0x37745961...BDd63FF50
0 ETH0.0012725923.67355335
Execute158346632022-10-26 20:33:23835 days ago1666816403IN
0x37745961...BDd63FF50
0 ETH0.0013174117.58294351
Execute158346432022-10-26 20:29:11835 days ago1666816151IN
0x37745961...BDd63FF50
0 ETH0.0060061816.64644001
Execute158346412022-10-26 20:28:47835 days ago1666816127IN
0x37745961...BDd63FF50
0 ETH0.0012758916.59070944
Execute157808272022-10-19 8:01:35842 days ago1666166495IN
0x37745961...BDd63FF50
0 ETH0.0034737824.38071672
Execute156752582022-10-04 14:07:11857 days ago1664892431IN
0x37745961...BDd63FF50
0 ETH0.0108507224.64931383
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
180189262023-08-29 7:55:23528 days ago1693295723
0x37745961...BDd63FF50
0.00171701 ETH
180189262023-08-29 7:55:23528 days ago1693295723
0x37745961...BDd63FF50
0.2 ETH
180189232023-08-29 7:54:47528 days ago1693295687
0x37745961...BDd63FF50
0.00420085 ETH
180188692023-08-29 7:43:59528 days ago1693295039
0x37745961...BDd63FF50
0.00605248 ETH
180188692023-08-29 7:43:59528 days ago1693295039
0x37745961...BDd63FF50
0.12358276 ETH
179328242023-08-17 6:43:23540 days ago1692254603
0x37745961...BDd63FF50
0.00159795 ETH
179328242023-08-17 6:43:23540 days ago1692254603
0x37745961...BDd63FF50
0.9 ETH
178846722023-08-10 13:05:59547 days ago1691672759
0x37745961...BDd63FF50
0.00925004 ETH
178846722023-08-10 13:05:59547 days ago1691672759
0x37745961...BDd63FF50
0.46 ETH
173861432023-06-01 13:05:47617 days ago1685624747
0x37745961...BDd63FF50
0.01155837 ETH
173861382023-06-01 13:04:47617 days ago1685624687
0x37745961...BDd63FF50
1.17454683 ETH
172875442023-05-18 16:12:11631 days ago1684426331
0x37745961...BDd63FF50
0.2 ETH
172875072023-05-18 16:04:35631 days ago1684425875
0x37745961...BDd63FF50
0.1 ETH
172718212023-05-16 10:57:11633 days ago1684234631
0x37745961...BDd63FF50
4.10774884 ETH
172657312023-05-15 14:20:23634 days ago1684160423
0x37745961...BDd63FF50
2.92 ETH
160963672022-12-02 9:56:23798 days ago1669974983
0x37745961...BDd63FF50
0.00106674 ETH
160963672022-12-02 9:56:23798 days ago1669974983
0x37745961...BDd63FF50
1.917 ETH
160963622022-12-02 9:55:23798 days ago1669974923
0x37745961...BDd63FF50
1.9011206 ETH
160963282022-12-02 9:48:35798 days ago1669974515
0x37745961...BDd63FF50
0.00152446 ETH
160963232022-12-02 9:47:35798 days ago1669974455
0x37745961...BDd63FF50
0.00210439 ETH
160963172022-12-02 9:46:23798 days ago1669974383
0x37745961...BDd63FF50
0.00453527 ETH
160962452022-12-02 9:31:59798 days ago1669973519
0x37745961...BDd63FF50
0.012 ETH
160962102022-12-02 9:24:59798 days ago1669973099
0x37745961...BDd63FF50
0.00155749 ETH
160962052022-12-02 9:23:59798 days ago1669973039
0x37745961...BDd63FF50
0.00173238 ETH
160962052022-12-02 9:23:59798 days ago1669973039
0x37745961...BDd63FF50
0.00105149 ETH
View All Internal Transactions
Loading...
Loading

Minimal Proxy Contract for 0x2a2b85eb1054d6f0c6c2e37da05ed3e5fea684ef

Contract Name:
Identity

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
/**
 *Submitted for verification at Etherscan.io on 2021-11-14
*/

pragma solidity 0.8.7;

// @TODO: Formatting
library LibBytes {
  // @TODO: see if we can just set .length = 
  function trimToSize(bytes memory b, uint newLen)
    internal
    pure
  {
    require(b.length > newLen, "BytesLib: only shrinking");
    assembly {
      mstore(b, newLen)
    }
  }


  /***********************************|
  |        Read Bytes Functions       |
  |__________________________________*/

  /**
   * @dev Reads a bytes32 value from a position in a byte array.
   * @param b Byte array containing a bytes32 value.
   * @param index Index in byte array of bytes32 value.
   * @return result bytes32 value from byte array.
   */
  function readBytes32(
    bytes memory b,
    uint256 index
  )
    internal
    pure
    returns (bytes32 result)
  {
    // Arrays are prefixed by a 256 bit length parameter
    index += 32;

    require(b.length >= index, "BytesLib: length");

    // Read the bytes32 from array memory
    assembly {
      result := mload(add(b, index))
    }
    return result;
  }
}



interface IERC1271Wallet {
	function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue);
}

library SignatureValidator {
	using LibBytes for bytes;

	enum SignatureMode {
		EIP712,
		EthSign,
		SmartWallet,
		Spoof
	}

	// bytes4(keccak256("isValidSignature(bytes32,bytes)"))
	bytes4 constant internal ERC1271_MAGICVALUE_BYTES32 = 0x1626ba7e;

	function recoverAddr(bytes32 hash, bytes memory sig) internal view returns (address) {
		return recoverAddrImpl(hash, sig, false);
	}

	function recoverAddrImpl(bytes32 hash, bytes memory sig, bool allowSpoofing) internal view returns (address) {
		require(sig.length >= 1, "SV_SIGLEN");
		uint8 modeRaw;
		unchecked { modeRaw = uint8(sig[sig.length - 1]); }
		SignatureMode mode = SignatureMode(modeRaw);

		// {r}{s}{v}{mode}
		if (mode == SignatureMode.EIP712 || mode == SignatureMode.EthSign) {
			require(sig.length == 66, "SV_LEN");
			bytes32 r = sig.readBytes32(0);
			bytes32 s = sig.readBytes32(32);
			uint8 v = uint8(sig[64]);
			// Hesitant about this check: seems like this is something that has no business being checked on-chain
			require(v == 27 || v == 28, "SV_INVALID_V");
			if (mode == SignatureMode.EthSign) hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
			address signer = ecrecover(hash, v, r, s);
			require(signer != address(0), "SV_ZERO_SIG");
			return signer;
		// {sig}{verifier}{mode}
		} else if (mode == SignatureMode.SmartWallet) {
			// 32 bytes for the addr, 1 byte for the type = 33
			require(sig.length > 33, "SV_LEN_WALLET");
			uint newLen;
			unchecked {
				newLen = sig.length - 33;
			}
			IERC1271Wallet wallet = IERC1271Wallet(address(uint160(uint256(sig.readBytes32(newLen)))));
			sig.trimToSize(newLen);
			require(ERC1271_MAGICVALUE_BYTES32 == wallet.isValidSignature(hash, sig), "SV_WALLET_INVALID");
			return address(wallet);
		// {address}{mode}; the spoof mode is used when simulating calls
		} else if (mode == SignatureMode.Spoof && allowSpoofing) {
			require(tx.origin == address(1), "SV_SPOOF_ORIGIN");
			require(sig.length == 33, "SV_SPOOF_LEN");
			sig.trimToSize(32);
			return abi.decode(sig, (address));
		} else revert("SV_SIGMODE");
	}
}


contract Identity {
	mapping (address => bytes32) public privileges;
	// The next allowed nonce
	uint public nonce;

	// Events
	event LogPrivilegeChanged(address indexed addr, bytes32 priv);
	event LogErr(address indexed to, uint value, bytes data, bytes returnData); // only used in tryCatch

	// Transaction structure
	// we handle replay protection separately by requiring (address(this), chainID, nonce) as part of the sig
	struct Transaction {
		address to;
		uint value;
		bytes data;
	}

	constructor(address[] memory addrs) {
		uint len = addrs.length;
		for (uint i=0; i<len; i++) {
			// @TODO should we allow setting to any arb value here?
			privileges[addrs[i]] = bytes32(uint(1));
			emit LogPrivilegeChanged(addrs[i], bytes32(uint(1)));
		}
	}

	// This contract can accept ETH without calldata
	receive() external payable {}

	// This contract can accept ETH with calldata
	// However, to support EIP 721 and EIP 1155, we need to respond to those methods with their own method signature
	fallback() external payable {
		bytes4 method = msg.sig;
		if (
			method == 0x150b7a02 // bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))
				|| method == 0xf23a6e61 // bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))
				|| method == 0xbc197c81 // bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))
		) {
			// Copy back the method
			// solhint-disable-next-line no-inline-assembly
			assembly {
				calldatacopy(0, 0, 0x04)
				return (0, 0x20)
			}
		}
	}

	function setAddrPrivilege(address addr, bytes32 priv)
		external
	{
		require(msg.sender == address(this), 'ONLY_IDENTITY_CAN_CALL');
		// Anti-bricking measure: if the privileges slot is used for special data (not 0x01),
		// don't allow to set it to true
		if (uint(privileges[addr]) > 1) require(priv != bytes32(uint(1)), 'UNSETTING_SPECIAL_DATA');
		privileges[addr] = priv;
		emit LogPrivilegeChanged(addr, priv);
	}

	function tipMiner(uint amount)
		external
	{
		require(msg.sender == address(this), 'ONLY_IDENTITY_CAN_CALL');
		// See https://docs.flashbots.net/flashbots-auction/searchers/advanced/coinbase-payment/#managing-payments-to-coinbaseaddress-when-it-is-a-contract
		// generally this contract is reentrancy proof cause of the nonce
		executeCall(block.coinbase, amount, new bytes(0));
	}

	function tryCatch(address to, uint value, bytes calldata data)
		external
	{
		require(msg.sender == address(this), 'ONLY_IDENTITY_CAN_CALL');
		(bool success, bytes memory returnData) = to.call{value: value, gas: gasleft()}(data);
		if (!success) emit LogErr(to, value, data, returnData);
	}


	// WARNING: if the signature of this is changed, we have to change IdentityFactory
	function execute(Transaction[] calldata txns, bytes calldata signature)
		external
	{
		require(txns.length > 0, 'MUST_PASS_TX');
		uint currentNonce = nonce;
		// NOTE: abi.encode is safer than abi.encodePacked in terms of collision safety
		bytes32 hash = keccak256(abi.encode(address(this), block.chainid, currentNonce, txns));
		// We have to increment before execution cause it protects from reentrancies
		nonce = currentNonce + 1;

		address signer = SignatureValidator.recoverAddrImpl(hash, signature, true);
		require(privileges[signer] != bytes32(0), 'INSUFFICIENT_PRIVILEGE');
		uint len = txns.length;
		for (uint i=0; i<len; i++) {
			Transaction memory txn = txns[i];
			executeCall(txn.to, txn.value, txn.data);
		}
		// The actual anti-bricking mechanism - do not allow a signer to drop their own priviledges
		require(privileges[signer] != bytes32(0), 'PRIVILEGE_NOT_DOWNGRADED');
	}

	// no need for nonce management here cause we're not dealing with sigs
	function executeBySender(Transaction[] calldata txns) external {
		require(txns.length > 0, 'MUST_PASS_TX');
		require(privileges[msg.sender] != bytes32(0), 'INSUFFICIENT_PRIVILEGE');
		uint len = txns.length;
		for (uint i=0; i<len; i++) {
			Transaction memory txn = txns[i];
			executeCall(txn.to, txn.value, txn.data);
		}
		// again, anti-bricking
		require(privileges[msg.sender] != bytes32(0), 'PRIVILEGE_NOT_DOWNGRADED');
	}

	function executeBySelf(Transaction[] calldata txns) external {
		require(msg.sender == address(this), 'ONLY_IDENTITY_CAN_CALL');
		require(txns.length > 0, 'MUST_PASS_TX');
		uint len = txns.length;
		for (uint i=0; i<len; i++) {
			Transaction memory txn = txns[i];
			executeCall(txn.to, txn.value, txn.data);
		}
	}

	// we shouldn't use address.call(), cause: https://github.com/ethereum/solidity/issues/2884
	// copied from https://github.com/uport-project/uport-identity/blob/develop/contracts/Proxy.sol
	// there's also
	// https://github.com/gnosis/MultiSigWallet/commit/e1b25e8632ca28e9e9e09c81bd20bf33fdb405ce
	// https://github.com/austintgriffith/bouncer-proxy/blob/master/BouncerProxy/BouncerProxy.sol
	// https://github.com/gnosis/safe-contracts/blob/7e2eeb3328bb2ae85c36bc11ea6afc14baeb663c/contracts/base/Executor.sol
	function executeCall(address to, uint256 value, bytes memory data)
		internal
	{
		assembly {
			let result := call(gas(), to, value, add(data, 0x20), mload(data), 0, 0)

			switch result case 0 {
				let size := returndatasize()
				let ptr := mload(0x40)
				returndatacopy(ptr, 0, size)
				revert(ptr, size)
			}
			default {}
		}
		// A single call consumes around 477 more gas with the pure solidity version, for whatever reason
		// WARNING: do not use this, it corrupts the returnData string (returns it in a slightly different format)
		//(bool success, bytes memory returnData) = to.call{value: value, gas: gasleft()}(data);
		//if (!success) revert(string(data));
	}

	// EIP 1271 implementation
	// see https://eips.ethereum.org/EIPS/eip-1271
	function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4) {
		if (privileges[SignatureValidator.recoverAddr(hash, signature)] != bytes32(0)) {
			// bytes4(keccak256("isValidSignature(bytes32,bytes)")
			return 0x1626ba7e;
		} else {
			return 0xffffffff;
		}
	}

	// EIP 1155 implementation
	// we pretty much only need to signal that we support the interface for 165, but for 1155 we also need the fallback function
	function supportsInterface(bytes4 interfaceID) external pure returns (bool) {
		return
			interfaceID == 0x01ffc9a7 ||    // ERC-165 support (i.e. `bytes4(keccak256('supportsInterface(bytes4)'))`).
			interfaceID == 0x4e2312e0;      // ERC-1155 `ERC1155TokenReceiver` support (i.e. `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)")) ^ bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`).
	}
}

Contract ABI

[{"inputs":[{"internalType":"address[]","name":"addrs","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"returnData","type":"bytes"}],"name":"LogErr","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"bytes32","name":"priv","type":"bytes32"}],"name":"LogPrivilegeChanged","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Identity.Transaction[]","name":"txns","type":"tuple[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Identity.Transaction[]","name":"txns","type":"tuple[]"}],"name":"executeBySelf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Identity.Transaction[]","name":"txns","type":"tuple[]"}],"name":"executeBySender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"privileges","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bytes32","name":"priv","type":"bytes32"}],"name":"setAddrPrivilege","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"tipMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"tryCatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ 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.