ETH Price: $3,268.54 (+0.65%)
Gas: 2 Gwei

Contract

0xfd102Bd9692ba05F6cc4547cb10d2765B5A4bC94
 
Transaction Hash
Method
Block
From
To
Execute202628072024-07-08 15:52:4719 days ago1720453967IN
0xfd102Bd9...5B5A4bC94
0 ETH0.001622018.05888671
Transfer202601972024-07-08 7:06:4719 days ago1720422407IN
0xfd102Bd9...5B5A4bC94
0.5295 ETH0.000122835.18027767
Execute202594082024-07-08 4:28:3519 days ago1720412915IN
0xfd102Bd9...5B5A4bC94
0 ETH0.000628563.16638671
Transfer202593712024-07-08 4:21:1119 days ago1720412471IN
0xfd102Bd9...5B5A4bC94
0.2 ETH0.000033081.39511376
Execute201528822024-06-23 7:22:5934 days ago1719127379IN
0xfd102Bd9...5B5A4bC94
0 ETH0.000526724.29952335
Execute201520792024-06-23 4:41:2334 days ago1719117683IN
0xfd102Bd9...5B5A4bC94
0 ETH0.00023833.51506109
Execute201520692024-06-23 4:39:2334 days ago1719117563IN
0xfd102Bd9...5B5A4bC94
0 ETH0.004117083.81390927
Execute201520552024-06-23 4:36:3534 days ago1719117395IN
0xfd102Bd9...5B5A4bC94
0 ETH0.000324933.58230203
Execute201520482024-06-23 4:35:1134 days ago1719117311IN
0xfd102Bd9...5B5A4bC94
0 ETH0.004602093.7355815
Execute201520442024-06-23 4:34:2334 days ago1719117263IN
0xfd102Bd9...5B5A4bC94
0 ETH0.000294483.61216572
Execute201308342024-06-20 5:24:1137 days ago1718861051IN
0xfd102Bd9...5B5A4bC94
0 ETH0.001222786.3808385
Execute201308302024-06-20 5:23:2337 days ago1718861003IN
0xfd102Bd9...5B5A4bC94
0 ETH0.000419335.67607626
Execute198661932024-05-14 5:33:5974 days ago1715664839IN
0xfd102Bd9...5B5A4bC94
0 ETH0.000947517.03703339
Execute198661902024-05-14 5:33:2374 days ago1715664803IN
0xfd102Bd9...5B5A4bC94
0 ETH0.001849557.33137688
Execute198661852024-05-14 5:32:2374 days ago1715664743IN
0xfd102Bd9...5B5A4bC94
0 ETH0.000646417.48109624
Execute198413422024-05-10 18:11:1177 days ago1715364671IN
0xfd102Bd9...5B5A4bC94
0 ETH0.002627417.19507589
Execute196520292024-04-14 6:37:11104 days ago1713076631IN
0xfd102Bd9...5B5A4bC94
0 ETH0.0010637213.1577911
Execute196520192024-04-14 6:35:11104 days ago1713076511IN
0xfd102Bd9...5B5A4bC94
0 ETH0.00121714.24717285
Execute196520102024-04-14 6:33:11104 days ago1713076391IN
0xfd102Bd9...5B5A4bC94
0 ETH0.0016788713.39620115
Execute196075092024-04-08 0:53:35110 days ago1712537615IN
0xfd102Bd9...5B5A4bC94
0 ETH0.0009366513.0734965
Execute196074922024-04-08 0:50:11110 days ago1712537411IN
0xfd102Bd9...5B5A4bC94
0 ETH0.0029836111.97603507
Execute196074902024-04-08 0:49:47110 days ago1712537387IN
0xfd102Bd9...5B5A4bC94
0 ETH0.0010619612.66490013
Execute194950082024-03-23 4:46:11126 days ago1711169171IN
0xfd102Bd9...5B5A4bC94
0 ETH0.0026756218.48711948
Execute194806822024-03-21 4:31:35128 days ago1710995495IN
0xfd102Bd9...5B5A4bC94
0 ETH0.0027713829.9341023
Execute194806732024-03-21 4:29:47128 days ago1710995387IN
0xfd102Bd9...5B5A4bC94
0 ETH0.0063768127.84087038
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
202628072024-07-08 15:52:4719 days ago1720453967
0xfd102Bd9...5B5A4bC94
0.00253212 ETH
202628072024-07-08 15:52:4719 days ago1720453967
0xfd102Bd9...5B5A4bC94
0.527 ETH
202594082024-07-08 4:28:3519 days ago1720412915
0xfd102Bd9...5B5A4bC94
0.2 ETH
201528822024-06-23 7:22:5934 days ago1719127379
0xfd102Bd9...5B5A4bC94
0.03 ETH
201520692024-06-23 4:39:2334 days ago1719117563
0xfd102Bd9...5B5A4bC94
0.00505813 ETH
201520552024-06-23 4:36:3534 days ago1719117395
0xfd102Bd9...5B5A4bC94
0.00038885 ETH
201520482024-06-23 4:35:1134 days ago1719117311
0xfd102Bd9...5B5A4bC94
0.00612567 ETH
201520442024-06-23 4:34:2334 days ago1719117263
0xfd102Bd9...5B5A4bC94
0.00035031 ETH
201308342024-06-20 5:24:1137 days ago1718861051
0xfd102Bd9...5B5A4bC94
0.00210506 ETH
198661932024-05-14 5:33:5974 days ago1715664839
0xfd102Bd9...5B5A4bC94
0.00110268 ETH
198661902024-05-14 5:33:2374 days ago1715664803
0xfd102Bd9...5B5A4bC94
0.00256613 ETH
198661852024-05-14 5:32:2374 days ago1715664743
0xfd102Bd9...5B5A4bC94
0.00090764 ETH
198413422024-05-10 18:11:1177 days ago1715364671
0xfd102Bd9...5B5A4bC94
0.00323776 ETH
196520292024-04-14 6:37:11104 days ago1713076631
0xfd102Bd9...5B5A4bC94
0.00178928 ETH
196520192024-04-14 6:35:11104 days ago1713076511
0xfd102Bd9...5B5A4bC94
0.00163873 ETH
196075092024-04-08 0:53:35110 days ago1712537615
0xfd102Bd9...5B5A4bC94
0.00158351 ETH
196074922024-04-08 0:50:11110 days ago1712537411
0xfd102Bd9...5B5A4bC94
0.0041857 ETH
196074902024-04-08 0:49:47110 days ago1712537387
0xfd102Bd9...5B5A4bC94
0.00154063 ETH
194950082024-03-23 4:46:11126 days ago1711169171
0xfd102Bd9...5B5A4bC94
0.00302674 ETH
194806822024-03-21 4:31:35128 days ago1710995495
0xfd102Bd9...5B5A4bC94
0.00393461 ETH
194806732024-03-21 4:29:47128 days ago1710995387
0xfd102Bd9...5B5A4bC94
0.01072603 ETH
194806522024-03-21 4:25:23128 days ago1710995123
0xfd102Bd9...5B5A4bC94
0.00326234 ETH
194806502024-03-21 4:24:59128 days ago1710995099
0xfd102Bd9...5B5A4bC94
0.00344017 ETH
194806362024-03-21 4:22:11128 days ago1710994931
0xfd102Bd9...5B5A4bC94
0.00473735 ETH
194170132024-03-12 5:48:47137 days ago1710222527
0xfd102Bd9...5B5A4bC94
0.00582538 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.