Gelato-automations/contracts/dependencies/InstaDapp/dsa-contracts/list.sol
2020-11-16 17:58:36 +01:00

164 lines
5.7 KiB
Solidity

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 =
0x0000000000000000000000000000000000000000;
// 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;
}
}