Transaction Hash:
Block:
12729936 at Jun-29-2021 04:08:16 PM +UTC
Transaction Fee:
0.006052475 ETH
$11.99
Gas Used:
242,099 Gas / 25 Gwei
Emitted Events:
| 194 |
0xc2e5d9937f81d87dbf07ce5af1ade6e215412f01.0xf2655ca50c134f2081360f02a1bf4714b79d312ffc82f90953fbb323f76d2e16( 0xf2655ca50c134f2081360f02a1bf4714b79d312ffc82f90953fbb323f76d2e16, 0x000000000000000000000000119b49a1c266c67656d098c320b697cc5ce94c43 )
|
| 195 |
InstaIndex.LogAccountCreated( sender=[Sender] 0x119b49a1c266c67656d098c320b697cc5ce94c43, owner=[Sender] 0x119b49a1c266c67656d098c320b697cc5ce94c43, account=0xc2e5d9937f81d87dbf07ce5af1ade6e215412f01, origin=0x00000000...000000000 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x119b49A1...C5Ce94C43 |
3.846415505697726658 Eth
Nonce: 533
|
3.840363030697726658 Eth
Nonce: 534
| 0.006052475 | ||
| 0x2971AdFa...A9c74f723 | (InstaDApp: Index) | ||||
| 0x4c8a1BEb...55194AbEb | (InstaDApp: List) | ||||
|
0x5A0b54D5...D3E029c4c
Miner
| (Spark Pool) | 16.027494165587012282 Eth | 16.033546640587012282 Eth | 0.006052475 | |
| 0xC2E5D993...215412F01 |
0 Eth
Nonce: 0
|
0 Eth
Nonce: 1
|
Execution Trace
InstaIndex.build( _owner=0x119b49A1C266c67656d098c320b697cC5Ce94C43, accountVersion=2, _origin=0x0000000000000000000000000000000000000000 ) => ( _account=0xC2E5D9937F81d87DBf07cE5af1adE6e215412F01 )
-
0xc2e5d9937f81d87dbf07ce5af1ade6e215412f01.3d602d80( ) -
InstaList.init( _account=0xC2E5D9937F81d87DBf07cE5af1adE6e215412F01 ) 0xc2e5d9937f81d87dbf07ce5af1ade6e215412f01.5bfa1b68( )InstaAccountV2.5bfa1b68( )-
InstaImplementations.getImplementation( _sig=System.Byte[] ) => ( 0x28aDcDC02Ca7B3EDf11924102726066AA0fA7010 )
-
build[InstaIndex (ln:170)]
createClone[InstaIndex (ln:176)]init[InstaIndex (ln:177)]enable[InstaIndex (ln:178)]LogAccountCreated[InstaIndex (ln:179)]
File 1 of 5: InstaIndex
File 2 of 5: InstaList
File 3 of 5: InstaAccountV2
File 4 of 5: InstaImplementations
File 5 of 5: InstaDefaultImplementation
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
/**
* @title InstaIndex
* @dev Main Contract For DeFi Smart Accounts. This is also a factory contract, Which deploys new Smart Account.
* Also Registry for DeFi Smart Accounts.
*/
interface AccountInterface {
function version() external view returns (uint);
function enable(address authority) external;
function cast(address[] calldata _targets, bytes[] calldata _datas, address _origin) external payable returns (bytes32[] memory responses);
}
interface ListInterface {
function init(address _account) external;
}
contract AddressIndex {
event LogNewMaster(address indexed master);
event LogUpdateMaster(address indexed master);
event LogNewCheck(uint indexed accountVersion, address indexed check);
event LogNewAccount(address indexed _newAccount, address indexed _connectors, address indexed _check);
// New Master Address.
address private newMaster;
// Master Address.
address public master;
// List Registry Address.
address public list;
// Connectors Modules(Account Module Version => Connectors Registry Module Address).
mapping (uint => address) public connectors;
// Check Modules(Account Module Version => Check Module Address).
mapping (uint => address) public check;
// Account Modules(Account Module Version => Account Module Address).
mapping (uint => address) public account;
// Version Count of Account Modules.
uint public versionCount;
/**
* @dev Throws if the sender not is Master Address.
*/
modifier isMaster() {
require(msg.sender == master, "not-master");
_;
}
/**
* @dev Change the Master Address.
* @param _newMaster New Master Address.
*/
function changeMaster(address _newMaster) external isMaster {
require(_newMaster != master, "already-a-master");
require(_newMaster != address(0), "not-valid-address");
require(newMaster != _newMaster, "already-a-new-master");
newMaster = _newMaster;
emit LogNewMaster(_newMaster);
}
function updateMaster() external {
require(newMaster != address(0), "not-valid-address");
require(msg.sender == newMaster, "not-master");
master = newMaster;
newMaster = address(0);
emit LogUpdateMaster(master);
}
/**
* @dev Change the Check Address of a specific Account Module version.
* @param accountVersion Account Module version.
* @param _newCheck The New Check Address.
*/
function changeCheck(uint accountVersion, address _newCheck) external isMaster {
require(_newCheck != check[accountVersion], "already-a-check");
check[accountVersion] = _newCheck;
emit LogNewCheck(accountVersion, _newCheck);
}
/**
* @dev Add New Account Module.
* @param _newAccount The New Account Module Address.
* @param _connectors Connectors Registry Module Address.
* @param _check Check Module Address.
*/
function addNewAccount(address _newAccount, address _connectors, address _check) external isMaster {
require(_newAccount != address(0), "not-valid-address");
versionCount++;
require(AccountInterface(_newAccount).version() == versionCount, "not-valid-version");
account[versionCount] = _newAccount;
if (_connectors != address(0)) connectors[versionCount] = _connectors;
if (_check != address(0)) check[versionCount] = _check;
emit LogNewAccount(_newAccount, _connectors, _check);
}
}
contract CloneFactory is AddressIndex {
/**
* @dev Clone a new Account Module.
* @param version Account Module version to clone.
*/
function createClone(uint version) internal returns (address result) {
bytes20 targetBytes = bytes20(account[version]);
// solium-disable-next-line security/no-inline-assembly
assembly {
let clone := mload(0x40)
mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(clone, 0x14), targetBytes)
mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
result := create(0, clone, 0x37)
}
}
/**
* @dev Check if Account Module is a clone.
* @param version Account Module version.
* @param query Account Module Address.
*/
function isClone(uint version, address query) external view returns (bool result) {
bytes20 targetBytes = bytes20(account[version]);
// solium-disable-next-line security/no-inline-assembly
assembly {
let clone := mload(0x40)
mstore(clone, 0x363d3d373d3d3d363d7300000000000000000000000000000000000000000000)
mstore(add(clone, 0xa), targetBytes)
mstore(add(clone, 0x1e), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
let other := add(clone, 0x40)
extcodecopy(query, other, 0, 0x2d)
result := and(
eq(mload(clone), mload(other)),
eq(mload(add(clone, 0xd)), mload(add(other, 0xd)))
)
}
}
}
contract InstaIndex is CloneFactory {
event LogAccountCreated(address sender, address indexed owner, address indexed account, address indexed origin);
/**
* @dev Create a new DeFi Smart Account for a user and run cast function in the new Smart Account.
* @param _owner Owner of the Smart Account.
* @param accountVersion Account Module version.
* @param _targets Array of Target to run cast function.
* @param _datas Array of Data(callData) to run cast function.
* @param _origin Where Smart Account is created.
*/
function buildWithCast(
address _owner,
uint accountVersion,
address[] calldata _targets,
bytes[] calldata _datas,
address _origin
) external payable returns (address _account) {
_account = build(_owner, accountVersion, _origin);
if (_targets.length > 0) AccountInterface(_account).cast.value(msg.value)(_targets, _datas, _origin);
}
/**
* @dev Create a new DeFi Smart Account for a user.
* @param _owner Owner of the Smart Account.
* @param accountVersion Account Module version.
* @param _origin Where Smart Account is created.
*/
function build(
address _owner,
uint accountVersion,
address _origin
) public returns (address _account) {
require(accountVersion != 0 && accountVersion <= versionCount, "not-valid-account");
_account = createClone(accountVersion);
ListInterface(list).init(_account);
AccountInterface(_account).enable(_owner);
emit LogAccountCreated(msg.sender, _owner, _account, _origin);
}
/**
* @dev Setup Initial things for InstaIndex, after its been deployed and can be only run once.
* @param _master The Master Address.
* @param _list The List Address.
* @param _account The Account Module Address.
* @param _connectors The Connectors Registry Module Address.
*/
function setBasics(
address _master,
address _list,
address _account,
address _connectors
) external {
require(
master == address(0) &&
list == address(0) &&
account[1] == address(0) &&
connectors[1] == address(0) &&
versionCount == 0,
"already-defined"
);
master = _master;
list = _list;
versionCount++;
account[versionCount] = _account;
connectors[versionCount] = _connectors;
}
}File 2 of 5: InstaList
pragma solidity ^0.6.0;
/**
* @title InstaList
* @dev Registry For DeFi Smart Account Authorised user.
*/
interface AccountInterface {
function isAuth(address _user) external view returns (bool);
}
contract DSMath {
function add(uint64 x, uint64 y) internal pure returns (uint64 z) {
require((z = x + y) >= x, "ds-math-add-overflow");
}
function sub(uint64 x, uint64 y) internal pure returns (uint64 z) {
require((z = x - y) <= x, "ds-math-sub-underflow");
}
}
contract Variables is DSMath {
// InstaIndex Address.
address public constant instaIndex = 0x2971AdFa57b20E5a416aE5a708A8655A9c74f723;
// Smart Account Count.
uint64 public accounts;
// Smart Account ID (Smart Account Address => Account ID).
mapping (address => uint64) public accountID;
// Smart Account Address (Smart Account ID => Smart Account Address).
mapping (uint64 => address) public accountAddr;
// User Link (User Address => UserLink(Account ID of First and Last And Count of Smart Accounts)).
mapping (address => UserLink) public userLink;
// Linked List of Users (User Address => Smart Account ID => UserList(Previous and next Account ID)).
mapping (address => mapping(uint64 => UserList)) public userList;
struct UserLink {
uint64 first;
uint64 last;
uint64 count;
}
struct UserList {
uint64 prev;
uint64 next;
}
// Account Link (Smart Account ID => AccountLink).
mapping (uint64 => AccountLink) public accountLink; // account => account linked list connection
// Linked List of Accounts (Smart Account ID => Account Address => AccountList).
mapping (uint64 => mapping (address => AccountList)) public accountList; // account => user address => list
struct AccountLink {
address first;
address last;
uint64 count;
}
struct AccountList {
address prev;
address next;
}
}
contract Configure is Variables {
/**
* @dev Add Account to User Linked List.
* @param _owner Account Owner.
* @param _account Smart Account Address.
*/
function addAccount(address _owner, uint64 _account) internal {
if (userLink[_owner].last != 0) {
userList[_owner][_account].prev = userLink[_owner].last;
userList[_owner][userLink[_owner].last].next = _account;
}
if (userLink[_owner].first == 0) userLink[_owner].first = _account;
userLink[_owner].last = _account;
userLink[_owner].count = add(userLink[_owner].count, 1);
}
/**
* @dev Remove Account from User Linked List.
* @param _owner Account Owner/User.
* @param _account Smart Account Address.
*/
function removeAccount(address _owner, uint64 _account) internal {
uint64 _prev = userList[_owner][_account].prev;
uint64 _next = userList[_owner][_account].next;
if (_prev != 0) userList[_owner][_prev].next = _next;
if (_next != 0) userList[_owner][_next].prev = _prev;
if (_prev == 0) userLink[_owner].first = _next;
if (_next == 0) userLink[_owner].last = _prev;
userLink[_owner].count = sub(userLink[_owner].count, 1);
delete userList[_owner][_account];
}
/**
* @dev Add Owner to Account Linked List.
* @param _owner Account Owner.
* @param _account Smart Account Address.
*/
function addUser(address _owner, uint64 _account) internal {
if (accountLink[_account].last != address(0)) {
accountList[_account][_owner].prev = accountLink[_account].last;
accountList[_account][accountLink[_account].last].next = _owner;
}
if (accountLink[_account].first == address(0)) accountLink[_account].first = _owner;
accountLink[_account].last = _owner;
accountLink[_account].count = add(accountLink[_account].count, 1);
}
/**
* @dev Remove Owner from Account Linked List.
* @param _owner Account Owner.
* @param _account Smart Account Address.
*/
function removeUser(address _owner, uint64 _account) internal {
address _prev = accountList[_account][_owner].prev;
address _next = accountList[_account][_owner].next;
if (_prev != address(0)) accountList[_account][_prev].next = _next;
if (_next != address(0)) accountList[_account][_next].prev = _prev;
if (_prev == address(0)) accountLink[_account].first = _next;
if (_next == address(0)) accountLink[_account].last = _prev;
accountLink[_account].count = sub(accountLink[_account].count, 1);
delete accountList[_account][_owner];
}
}
contract InstaList is Configure {
/**
* @dev Enable Auth for Smart Account.
* @param _owner Owner Address.
*/
function addAuth(address _owner) external {
require(accountID[msg.sender] != 0, "not-account");
require(AccountInterface(msg.sender).isAuth(_owner), "not-owner");
addAccount(_owner, accountID[msg.sender]);
addUser(_owner, accountID[msg.sender]);
}
/**
* @dev Disable Auth for Smart Account.
* @param _owner Owner Address.
*/
function removeAuth(address _owner) external {
require(accountID[msg.sender] != 0, "not-account");
require(!AccountInterface(msg.sender).isAuth(_owner), "already-owner");
removeAccount(_owner, accountID[msg.sender]);
removeUser(_owner, accountID[msg.sender]);
}
/**
* @dev Setup Initial configuration of Smart Account.
* @param _account Smart Account Address.
*/
function init(address _account) external {
require(msg.sender == instaIndex, "not-index");
accounts++;
accountID[_account] = accounts;
accountAddr[accounts] = _account;
}
}File 3 of 5: InstaAccountV2
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
interface AccountImplementations {
function getImplementation(bytes4 _sig) external view returns (address);
}
/**
* @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
* instruction `delegatecall`.
*/
contract InstaAccountV2 {
AccountImplementations public immutable implementations;
constructor(address _implementations) {
implementations = AccountImplementations(_implementations);
}
/**
* @dev Delegates the current call to `implementation`.
*
* This function does not return to its internall call site, it will return directly to the external caller.
*/
function _delegate(address implementation) internal {
// solhint-disable-next-line no-inline-assembly
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
/**
* @dev Delegates the current call to the address returned by Implementations registry.
*
* This function does not return to its internall call site, it will return directly to the external caller.
*/
function _fallback(bytes4 _sig) internal {
address _implementation = implementations.getImplementation(_sig);
require(_implementation != address(0), "InstaAccountV2: Not able to find _implementation");
_delegate(_implementation);
}
/**
* @dev Fallback function that delegates calls to the address returned by Implementations registry.
*/
fallback () external payable {
_fallback(msg.sig);
}
/**
* @dev Fallback function that delegates calls to the address returned by Implementations registry.
*/
receive () external payable {
if (msg.sig != 0x00000000) {
_fallback(msg.sig);
}
}
}
File 4 of 5: InstaImplementations
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
interface IndexInterface {
function master() external view returns (address);
}
contract Setup {
address public defaultImplementation;
mapping (bytes4 => address) internal sigImplementations;
mapping (address => bytes4[]) internal implementationSigs;
}
contract Implementations is Setup {
event LogSetDefaultImplementation(address indexed oldImplementation, address indexed newImplementation);
event LogAddImplementation(address indexed implementation, bytes4[] sigs);
event LogRemoveImplementation(address indexed implementation, bytes4[] sigs);
IndexInterface constant public instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723);
modifier isMaster() {
require(msg.sender == instaIndex.master(), "Implementations: not-master");
_;
}
function setDefaultImplementation(address _defaultImplementation) external isMaster {
require(_defaultImplementation != address(0), "Implementations: _defaultImplementation address not valid");
require(_defaultImplementation != defaultImplementation, "Implementations: _defaultImplementation cannot be same");
emit LogSetDefaultImplementation(defaultImplementation, _defaultImplementation);
defaultImplementation = _defaultImplementation;
}
function addImplementation(address _implementation, bytes4[] calldata _sigs) external isMaster {
require(_implementation != address(0), "Implementations: _implementation not valid.");
require(implementationSigs[_implementation].length == 0, "Implementations: _implementation already added.");
for (uint i = 0; i < _sigs.length; i++) {
bytes4 _sig = _sigs[i];
require(sigImplementations[_sig] == address(0), "Implementations: _sig already added");
sigImplementations[_sig] = _implementation;
}
implementationSigs[_implementation] = _sigs;
emit LogAddImplementation(_implementation, _sigs);
}
function removeImplementation(address _implementation) external isMaster {
require(_implementation != address(0), "Implementations: _implementation not valid.");
require(implementationSigs[_implementation].length != 0, "Implementations: _implementation not found.");
bytes4[] memory sigs = implementationSigs[_implementation];
for (uint i = 0; i < sigs.length; i++) {
bytes4 sig = sigs[i];
delete sigImplementations[sig];
}
delete implementationSigs[_implementation];
emit LogRemoveImplementation(_implementation, sigs);
}
}
contract InstaImplementations is Implementations {
function getImplementation(bytes4 _sig) external view returns (address) {
address _implementation = sigImplementations[_sig];
return _implementation == address(0) ? defaultImplementation : _implementation;
}
function getImplementationSigs(address _impl) external view returns (bytes4[] memory) {
return implementationSigs[_impl];
}
function getSigImplementation(bytes4 _sig) external view returns (address) {
return sigImplementations[_sig];
}
}
File 5 of 5: InstaDefaultImplementation
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
import { Variables } from "./variables.sol";
interface IndexInterface {
function list() external view returns (address);
}
interface ListInterface {
function addAuth(address user) external;
function removeAuth(address user) external;
}
contract Constants is Variables {
uint public constant implementationVersion = 1;
// InstaIndex Address.
address public constant instaIndex = 0x2971AdFa57b20E5a416aE5a708A8655A9c74f723;
// The Account Module Version.
uint public constant version = 2;
}
contract Record is Constants {
event LogEnableUser(address indexed user);
event LogDisableUser(address indexed user);
/**
* @dev Check for Auth if enabled.
* @param user address/user/owner.
*/
function isAuth(address user) public view returns (bool) {
return _auth[user];
}
/**
* @dev Enable New User.
* @param user Owner address
*/
function enable(address user) public {
require(msg.sender == address(this) || msg.sender == instaIndex, "not-self-index");
require(user != address(0), "not-valid");
require(!_auth[user], "already-enabled");
_auth[user] = true;
ListInterface(IndexInterface(instaIndex).list()).addAuth(user);
emit LogEnableUser(user);
}
/**
* @dev Disable User.
* @param user Owner address
*/
function disable(address user) public {
require(msg.sender == address(this), "not-self");
require(user != address(0), "not-valid");
require(_auth[user], "already-disabled");
delete _auth[user];
ListInterface(IndexInterface(instaIndex).list()).removeAuth(user);
emit LogDisableUser(user);
}
}
contract InstaDefaultImplementation is Record {
receive() external payable {}
}pragma solidity ^0.7.0;
contract Variables {
// Auth Module(Address of Auth => bool).
mapping (address => bool) internal _auth;
}