diff --git a/.github/workflows/status.yml b/.github/workflows/status.yml index 2e72f099..3382de78 100644 --- a/.github/workflows/status.yml +++ b/.github/workflows/status.yml @@ -29,7 +29,8 @@ jobs: - name: Run status checks id: status_check run: | - output=$(node ./status-checks) + # Run status checks, Remove ANSI colors from the text + output=$(node ./status-checks | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g') # Escape newlines so _all_ the output is included in the set-output output="${output//'%'/'%25'}" output="${output//$'\n'/'%0A'}" @@ -42,7 +43,7 @@ jobs: uses: bubkoo/auto-comment@v1 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - pullRequestSynchronize: "${{ steps.status_check.outputs.status_check_output }}" - pullRequestAssigned: "${{ steps.status_check.outputs.status_check_output }}" - pullRequestOpened: "${{ steps.status_check.outputs.status_check_output }}" - pullRequestReopened: "${{ steps.status_check.outputs.status_check_output }}" + pullRequestSynchronize: "```${{ steps.status_check.outputs.status_check_output }}```" + pullRequestAssigned: "```${{ steps.status_check.outputs.status_check_output }}```" + pullRequestOpened: "```${{ steps.status_check.outputs.status_check_output }}```" + pullRequestReopened: "```${{ steps.status_check.outputs.status_check_output }}```" diff --git a/README.md b/README.md index e9a60cd8..be1b4893 100644 --- a/README.md +++ b/README.md @@ -53,4 +53,3 @@ Few things to consider while writing the connector: ### Support If you can't find something you're looking for or have any questions, ask them at our developers community on [Discord](https://discord.gg/83vvrnY) or simply send an [Email](mailto:info@instadapp.io). - diff --git a/contracts/mainnet/connectors/basic-ERC1155/events.sol b/contracts/mainnet/connectors/basic-ERC1155/events.sol new file mode 100644 index 00000000..2ef9f79a --- /dev/null +++ b/contracts/mainnet/connectors/basic-ERC1155/events.sol @@ -0,0 +1,20 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDepositERC1155( + address indexed erc1155, + address from, + uint256 tokenId, + uint256 amount, + uint256 getId, + uint256 setId + ); + event LogWithdrawERC1155( + address indexed erc1155, + uint256 tokenId, + address indexed to, + uint256 amount, + uint256 getId, + uint256 setId + ); +} diff --git a/contracts/mainnet/connectors/basic-ERC1155/main.sol b/contracts/mainnet/connectors/basic-ERC1155/main.sol new file mode 100644 index 00000000..0aef5cd7 --- /dev/null +++ b/contracts/mainnet/connectors/basic-ERC1155/main.sol @@ -0,0 +1,93 @@ +pragma solidity ^0.7.0; + +/** + * @title Basic. + * @dev Deposit & Withdraw from ERC1155 DSA. + */ +import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; + +import {DSMath} from "../../common/math.sol"; +import {Basic} from "../../common/basic.sol"; +import {Events} from "./events.sol"; + +abstract contract BasicResolver is Events, DSMath, Basic { + /** + * @dev Deposit Assets To Smart Account. + * @notice Deposit a ERC1155 token to DSA + * @param token Address of token. + * @param tokenId ID of token. + * @param amount Amount to deposit. + * @param getId ID to retrieve amount. + * @param setId ID stores the amount. + */ + function depositERC1155( + address token, + uint256 tokenId, + uint256 amount, + uint256 getId, + uint256 setId + ) + public + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amount = getUint(getId, amount); + + IERC1155 tokenContract = IERC1155(token); + tokenContract.safeTransferFrom( + msg.sender, + address(this), + tokenId, + _amount, + "" + ); + + setUint(setId, _amount); + + _eventName = "LogDepositERC1155(address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode( + token, + msg.sender, + tokenId, + _amount, + getId, + setId + ); + } + + /** + * @dev Withdraw Assets To Smart Account. + * @notice Withdraw a ERC1155 token from DSA + * @param token Address of the token. + * @param tokenId ID of token. + * @param to The address to receive the token upon withdrawal + * @param amount Amount to withdraw. + * @param getId ID to retrieve amount. + * @param setId ID stores the amount. + */ + function withdrawERC1155( + address token, + uint256 tokenId, + address payable to, + uint256 amount, + uint256 getId, + uint256 setId + ) + public + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _amount = getUint(getId, amount); + IERC1155 tokenContract = IERC1155(token); + tokenContract.safeTransferFrom(address(this), to, tokenId, _amount, ""); + + setUint(setId, _amount); + + _eventName = "LogWithdrawERC1155(address,uint256,address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, tokenId, to, _amount, getId, setId); + } +} + +contract ConnectV2BasicERC1155 is BasicResolver { + string public constant name = "BASIC-ERC1155-v1.0"; +} diff --git a/contracts/mainnet/connectors/basic-ERC721/events.sol b/contracts/mainnet/connectors/basic-ERC721/events.sol new file mode 100644 index 00000000..7b367145 --- /dev/null +++ b/contracts/mainnet/connectors/basic-ERC721/events.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDepositERC721( + address indexed erc721, + address from, + uint256 tokenId, + uint256 getId, + uint256 setId + ); + event LogWithdrawERC721( + address indexed erc721, + uint256 tokenId, + address indexed to, + uint256 getId, + uint256 setId + ); +} diff --git a/contracts/mainnet/connectors/basic-ERC721/main.sol b/contracts/mainnet/connectors/basic-ERC721/main.sol new file mode 100644 index 00000000..410c6342 --- /dev/null +++ b/contracts/mainnet/connectors/basic-ERC721/main.sol @@ -0,0 +1,76 @@ +pragma solidity ^0.7.0; + +/** + * @title Basic. + * @dev Deposit & Withdraw ERC721 from DSA. + */ +import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; + +import {DSMath} from "../../common/math.sol"; +import {Basic} from "../../common/basic.sol"; +import {Events} from "./events.sol"; + +abstract contract BasicResolver is Events, DSMath, Basic { + /** + * @dev Deposit Assets To Smart Account. + * @notice Deposit a ERC721 token to DSA + * @param token Address of token. + * @param tokenId ID of token. + * @param getId ID to retrieve tokenId. + * @param setId ID stores the tokenId. + */ + function depositERC721( + address token, + uint256 tokenId, + uint256 getId, + uint256 setId + ) + public + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _tokenId = getUint(getId, tokenId); + + IERC721 tokenContract = IERC721(token); + tokenContract.safeTransferFrom(msg.sender, address(this), _tokenId); + + setUint(setId, _tokenId); + + _eventName = "LogDepositERC721(address,address,uint256,uint256,uint256)"; + _eventParam = abi.encode(token, msg.sender, _tokenId, getId, setId); + } + + /** + * @dev Withdraw Assets To Smart Account. + * @notice Withdraw a ERC721 token from DSA + * @param token Address of the token. + * @param tokenId ID of token. + * @param to The address to receive the token upon withdrawal + * @param getId ID to retrieve tokenId. + * @param setId ID stores the tokenId. + */ + function withdrawERC721( + address token, + uint256 tokenId, + address payable to, + uint256 getId, + uint256 setId + ) + public + payable + returns (string memory _eventName, bytes memory _eventParam) + { + uint256 _tokenId = getUint(getId, tokenId); + IERC721 tokenContract = IERC721(token); + tokenContract.safeTransferFrom(address(this), to, _tokenId); + + setUint(setId, _tokenId); + + _eventName = "LogWithdrawERC721(address,uint256,address,uint256,uint256)"; + _eventParam = abi.encode(token, _tokenId, to, getId, setId); + } +} + +contract ConnectV2BasicERC721 is BasicResolver { + string public constant name = "BASIC-ERC721-v1.0"; +} diff --git a/contracts/mainnet/connectors/guniswap_v3_erc20_staking/events.sol b/contracts/mainnet/connectors/guniswap_v3_erc20_staking/events.sol index 4e75acd1..6ad9d5fc 100644 --- a/contracts/mainnet/connectors/guniswap_v3_erc20_staking/events.sol +++ b/contracts/mainnet/connectors/guniswap_v3_erc20_staking/events.sol @@ -3,14 +3,14 @@ pragma solidity ^0.7.0; contract Events { event LogDeposit( - address indexed stakingToken, + address indexed stakingPool, uint256 amount, uint getId, uint setId ); event LogWithdrawAndClaimedReward( - address indexed stakingToken, + address indexed stakingPool, uint256 amount, uint256 rewardAmt, uint getId, @@ -19,6 +19,7 @@ contract Events { ); event LogClaimedReward( + address indexed stakingPool, address indexed rewardToken, uint256 rewardAmt, uint setId diff --git a/contracts/mainnet/connectors/guniswap_v3_erc20_staking/helpers.sol b/contracts/mainnet/connectors/guniswap_v3_erc20_staking/helpers.sol index 1d0c6d94..475567ef 100644 --- a/contracts/mainnet/connectors/guniswap_v3_erc20_staking/helpers.sol +++ b/contracts/mainnet/connectors/guniswap_v3_erc20_staking/helpers.sol @@ -8,17 +8,5 @@ import { TokenInterface } from "../../common/interfaces.sol"; import { IStakingRewards, IStakingRewardsFactory, IGUniPoolResolver } from "./interface.sol"; abstract contract Helpers is DSMath, Basic { - - IGUniPoolResolver constant internal guniResolver = - IGUniPoolResolver(0x729BF02a9A786529Fc80498f8fd0051116061B13); - TokenInterface constant internal rewardToken = TokenInterface(0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb); - - function getStakingContract(address stakingToken) internal view returns (address) { - IStakingRewardsFactory.StakingRewardsInfo memory stakingRewardsInfo = - guniResolver.getStakingFactory().stakingRewardsInfoByStakingToken(stakingToken); - - return stakingRewardsInfo.stakingRewards; - } - } \ No newline at end of file diff --git a/contracts/mainnet/connectors/guniswap_v3_erc20_staking/main.sol b/contracts/mainnet/connectors/guniswap_v3_erc20_staking/main.sol index 47a2d62a..a4c717de 100644 --- a/contracts/mainnet/connectors/guniswap_v3_erc20_staking/main.sol +++ b/contracts/mainnet/connectors/guniswap_v3_erc20_staking/main.sol @@ -17,12 +17,14 @@ contract Main is Helpers, Events { /** * @dev Deposit ERC20. * @notice Deposit Tokens to staking pool. + * @param stakingPool staking pool address. * @param stakingToken staking token address. * @param amt staking token amount. * @param getId ID to retrieve amount. * @param setId ID stores the amount of staked tokens. */ function deposit( + address stakingPool, address stakingToken, uint amt, uint getId, @@ -30,7 +32,7 @@ contract Main is Helpers, Events { ) external payable returns (string memory _eventName, bytes memory _eventParam) { uint _amt = getUint(getId, amt); - IStakingRewards stakingContract = IStakingRewards(getStakingContract(stakingToken)); + IStakingRewards stakingContract = IStakingRewards(stakingPool); TokenInterface stakingTokenContract = TokenInterface(stakingToken); _amt = _amt == uint(-1) ? stakingTokenContract.balanceOf(address(this)) : _amt; @@ -40,12 +42,13 @@ contract Main is Helpers, Events { setUint(setId, _amt); _eventName = "LogDeposit(address,uint256,uint256,uint256)"; - _eventParam = abi.encode(address(stakingToken), _amt, getId, setId); + _eventParam = abi.encode(address(stakingPool), _amt, getId, setId); } /** * @dev Withdraw ERC20. * @notice Withdraw Tokens from the staking pool. + * @param stakingPool staking pool address. * @param stakingToken staking token address. * @param amt staking token amount. * @param getId ID to retrieve amount. @@ -53,6 +56,7 @@ contract Main is Helpers, Events { * @param setIdReward ID stores the amount of reward tokens claimed. */ function withdraw( + address stakingPool, address stakingToken, uint amt, uint getId, @@ -61,7 +65,7 @@ contract Main is Helpers, Events { ) external payable returns (string memory _eventName, bytes memory _eventParam) { uint _amt = getUint(getId, amt); - IStakingRewards stakingContract = IStakingRewards(getStakingContract(stakingToken)); + IStakingRewards stakingContract = IStakingRewards(stakingPool); _amt = _amt == uint(-1) ? stakingContract.balanceOf(address(this)) : _amt; uint intialBal = rewardToken.balanceOf(address(this)); @@ -74,21 +78,21 @@ contract Main is Helpers, Events { setUint(setIdReward, rewardAmt); { _eventName = "LogWithdrawAndClaimedReward(address,uint256,uint256,uint256,uint256,uint256)"; - _eventParam = abi.encode(address(stakingToken), _amt, rewardAmt, getId, setIdAmount, setIdReward); + _eventParam = abi.encode(address(stakingPool), _amt, rewardAmt, getId, setIdAmount, setIdReward); } } /** * @dev Claim Reward. * @notice Claim Pending Rewards of tokens staked. - * @param stakingToken staking token address. + * @param stakingPool staking pool address. * @param setId ID stores the amount of reward tokens claimed. */ function claimReward( - address stakingToken, + address stakingPool, uint setId ) external payable returns (string memory _eventName, bytes memory _eventParam) { - IStakingRewards stakingContract = IStakingRewards(getStakingContract(stakingToken)); + IStakingRewards stakingContract = IStakingRewards(stakingPool); uint intialBal = rewardToken.balanceOf(address(this)); stakingContract.getReward(); @@ -97,12 +101,12 @@ contract Main is Helpers, Events { uint rewardAmt = sub(finalBal, intialBal); setUint(setId, rewardAmt); - _eventName = "LogClaimedReward(address,uint256,uint256)"; - _eventParam = abi.encode(address(rewardToken), rewardAmt, setId); + _eventName = "LogClaimedReward(address,address,uint256,uint256)"; + _eventParam = abi.encode(address(stakingPool), address(rewardToken), rewardAmt, setId); } } contract connectV2StakeGUNI is Main { - string public constant name = "Stake-G-UNI-v1.0"; + string public constant name = "Stake-G-UNI-v1.1"; } \ No newline at end of file diff --git a/contracts/mainnet/connectors/yearn_v2/events.sol b/contracts/mainnet/connectors/yearn_v2/events.sol new file mode 100644 index 00000000..f289044b --- /dev/null +++ b/contracts/mainnet/connectors/yearn_v2/events.sol @@ -0,0 +1,6 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogDeposit(address indexed vault, uint256 shareAmt, uint256 depositAmt, uint256 getId, uint256 setId); + event LogWithdraw(address indexed recipient, uint256 shareAmt, uint256 withdrawAmt, uint256 getId, uint256 setId); +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/yearn_v2/interface.sol b/contracts/mainnet/connectors/yearn_v2/interface.sol new file mode 100644 index 00000000..b72e6181 --- /dev/null +++ b/contracts/mainnet/connectors/yearn_v2/interface.sol @@ -0,0 +1,12 @@ +pragma solidity ^0.7.0; + +interface YearnV2Interface { + function deposit(uint256 amount, address recipient) external returns (uint256); + + function withdraw(uint256 maxShares, address recipient) external returns (uint256); + + function token() external view returns (address); + + function balanceOf(address owner) external view returns (uint256); +} + diff --git a/contracts/mainnet/connectors/yearn_v2/main.sol b/contracts/mainnet/connectors/yearn_v2/main.sol new file mode 100644 index 00000000..c8a238f3 --- /dev/null +++ b/contracts/mainnet/connectors/yearn_v2/main.sol @@ -0,0 +1,86 @@ +pragma solidity ^0.7.0; + +/** + * @title Yearn V2. + * @dev Vaults & yield. + */ + +import { TokenInterface } from "../../common/interfaces.sol"; +import { Basic } from "../../common/basic.sol"; +import { Events } from "./events.sol"; +import { YearnV2Interface } from "./interface.sol"; + +abstract contract YearnResolver is Events, Basic { + /** + * @dev Deposit funds in the vault, issuing shares to recipient. + * @notice This will deposit funds to a specific Yearn Vault. + * @param vault The address of the vault to deposit funds into. + * @param amt The amount of tokens to deposit. + * @param getId ID to retrieve amt. + * @param setId ID stores the amount of shares received. + */ + function deposit( + address vault, + uint256 amt, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + YearnV2Interface yearn = YearnV2Interface(vault); + + address want = yearn.token(); + bool iswETH = want == wethAddr; + TokenInterface tokenContract = TokenInterface(want); + + if (iswETH) { + _amt = _amt == uint(-1) ? address(this).balance : _amt; + convertEthToWeth(iswETH, tokenContract, _amt); + } else { + _amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt; + } + + approve(tokenContract, vault, _amt); + + uint256 _shares = yearn.deposit(_amt, address(this)); + setUint(setId, _shares); + + _eventName = "LogDeposit(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(vault, _shares, _amt, getId, setId); + } + + /** + * @dev Withdraw shares from the vault. + * @notice This will withdraw the share from a specific Yearn Vault. + * @param vault The address of the vault to withdraw shares from. + * @param amt The amount of shares to withdraw. + * @param getId ID to retrieve amt. + * @param setId ID stores the amount want token redeemed. + */ + function withdraw( + address vault, + uint256 amt, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + YearnV2Interface vault = YearnV2Interface(vault); + + + _amt = _amt == uint(-1) ? vault.balanceOf(address(this)) : _amt; + uint256 _wantRedeemed = vault.withdraw(_amt, address(this)); + setUint(setId, _wantRedeemed); + + TokenInterface tokenContract = TokenInterface(vault.token()); + bool isWEth = vault.token() == wethAddr; + convertWethToEth(isWEth, tokenContract, _amt); + + _eventName = "LogWithdraw(address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(vault, _amt, _wantRedeemed, getId, setId); + } +} + +contract ConnectV2YearnV2 is YearnResolver { + string public constant name = "YearnV2-v1.0"; +} diff --git a/contracts/test/implementation_default.sol b/contracts/test/implementation_default.sol new file mode 100644 index 00000000..e897433b --- /dev/null +++ b/contracts/test/implementation_default.sol @@ -0,0 +1,114 @@ +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 { + uint256 public constant implementationVersion = 1; + // InstaIndex Address. + address public immutable instaIndex; + // The Account Module Version. + uint256 public constant version = 2; + + constructor(address _instaIndex) { + instaIndex = _instaIndex; + } +} + +contract Record is Constants { + constructor(address _instaIndex) Constants(_instaIndex) {} + + 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); + } + + /** + * @dev ERC721 token receiver + */ + function onERC721Received( + address, + address, + uint256, + bytes calldata + ) external returns (bytes4) { + return 0x150b7a02; // bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")) + } + + /** + * @dev ERC1155 token receiver + */ + function onERC1155Received( + address, + address, + uint256, + uint256, + bytes memory + ) external returns (bytes4) { + return 0xf23a6e61; // bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)")) + } + + /** + * @dev ERC1155 token receiver + */ + function onERC1155BatchReceived( + address, + address, + uint256[] calldata, + uint256[] calldata, + bytes calldata + ) external returns (bytes4) { + return 0xbc197c81; // bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)")) + } +} + +contract InstaDefaultImplementation is Record { + constructor(address _instaIndex) public Record(_instaIndex) {} + + receive() external payable {} +} diff --git a/contracts/test/variables.sol b/contracts/test/variables.sol new file mode 100644 index 00000000..86853496 --- /dev/null +++ b/contracts/test/variables.sol @@ -0,0 +1,6 @@ +pragma solidity ^0.7.0; + +contract Variables { + // Auth Module(Address of Auth => bool). + mapping (address => bool) internal _auth; +} \ No newline at end of file diff --git a/hardhat.config.js b/hardhat.config.js index e6233d9c..896a5e96 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -63,7 +63,7 @@ module.exports = { hardhat: { forking: { url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`, - blockNumber: 13180514, + blockNumber: 12796965, }, blockGasLimit: 12000000, gasPrice: parseInt(utils.parseUnits("300", "gwei")) @@ -85,4 +85,4 @@ module.exports = { mocha: { timeout: 100 * 1000, }, -}; +}; \ No newline at end of file diff --git a/package.json b/package.json index dbb4e447..b0ee2f1f 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "scripts": { "test": "hardhat test", "coverage": "./node_modules/.bin/solidity-coverage", + "check": "node status-checks/huskyCheck.js", "check-husky": "node status-checks/huskyCheck.js", "deploy": "node scripts/deployConnectorsFromCmd.js", "build-contracts": "sol-merger \"./contracts/connectors/mock.sol\" ./contracts/build" diff --git a/scripts/constant/abi/core/InstaImplementations.json b/scripts/constant/abi/core/InstaImplementations.json new file mode 100644 index 00000000..c1bae964 --- /dev/null +++ b/scripts/constant/abi/core/InstaImplementations.json @@ -0,0 +1,206 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "InstaImplementations", + "sourceName": "contracts/v2/registry/implementations.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_instaIndex", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes4[]", + "name": "sigs", + "type": "bytes4[]" + } + ], + "name": "LogAddImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes4[]", + "name": "sigs", + "type": "bytes4[]" + } + ], + "name": "LogRemoveImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "LogSetDefaultImplementation", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "_sigs", + "type": "bytes4[]" + } + ], + "name": "addImplementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "defaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sig", + "type": "bytes4" + } + ], + "name": "getImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_impl", + "type": "address" + } + ], + "name": "getImplementationSigs", + "outputs": [ + { + "internalType": "bytes4[]", + "name": "", + "type": "bytes4[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sig", + "type": "bytes4" + } + ], + "name": "getSigImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "instaIndex", + "outputs": [ + { + "internalType": "contract IndexInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "removeImplementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_defaultImplementation", + "type": "address" + } + ], + "name": "setDefaultImplementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x60a060405234801561001057600080fd5b506040516116383803806116388339818101604052602081101561003357600080fd5b8101908080519060200190929190505050808073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b81525050505060805160601c61158e6100aa6000398061039f528061085b5280610c5d5280610dfb525061158e6000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063b39c45931161005b578063b39c4593146101e2578063dc9cc64514610216578063ef7e5c7b1461028d578063f0c01b421461030457610088565b806322175a321461008d5780637c16ffc4146100d157806389396dc814610115578063a41098bf146101ae575b600080fd5b6100cf600480360360208110156100a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061039d565b005b610113600480360360208110156100e757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610859565b005b6101576004803603602081101561012b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b82565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561019a57808201518184015260208101905061017f565b505050509050019250505060405180910390f35b6101b6610c5b565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101ea610c7f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102616004803603602081101561022c57600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610ca3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102d8600480360360208110156102a357600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610d7e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61039b6004803603604081101561031a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561035757600080fd5b82018360208201111561036957600080fd5b8035906020019184602083028401116401000000008311171561038b57600080fd5b9091929391929390505050610df9565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b15801561040357600080fd5b505afa158015610417573d6000803e3d6000fd5b505050506040513d602081101561042d57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610564576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114cd602b913960400191505060405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501415610600576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114f8602b913960400191505060405180910390fd5b6060600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156106cd57602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161067a5790505b5050505050905060005b815181101561077a5760008282815181106106ee57fe5b6020026020010151905060016000827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555080806001019150506106d7565b50600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006107c69190611305565b8173ffffffffffffffffffffffffffffffffffffffff167fb7d759e6cdda23e8a1749bce345fc77355b8a22eeaf92c6e4e7257d959c162c7826040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610842578082015181840152602081019050610827565b505050509050019250505060405180910390a25050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d60208110156108e957600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260398152602001806114656039913960400191505060405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610ac5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806115236036913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f3b337225b8d68d037e0c721876335a3832bd08162c943fe5f88e8d428597ca8f60405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6060600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610c4f57602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411610bfc5790505b50505050509050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d545780610d76565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b915050919050565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5f57600080fd5b505afa158015610e73573d6000803e3d6000fd5b505050506040513d6020811015610e8957600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610f3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610fc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114cd602b913960400191505060405180910390fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501461105b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061149e602f913960400191505060405180910390fd5b60005b8282905081101561123357600083838381811061107757fe5b905060200201357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169050600073ffffffffffffffffffffffffffffffffffffffff1660016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611195576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806114426023913960400191505060405180910390fd5b8460016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050808060010191505061105e565b508181600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020919061128292919061132d565b508273ffffffffffffffffffffffffffffffffffffffff167ff9c512a86be00aaec236065d0a439f064133f367de889c782448c3578a3f30c5838360405180806020018281038252848482818152602001925060200280828437600081840152601f19601f820116905080830192505050935050505060405180910390a2505050565b50805460008255600701600890049060005260206000209081019061132a91906113f9565b50565b828054828255906000526020600020906007016008900481019282156113e85791602002820160005b838211156113b65783357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191683826101000a81548163ffffffff021916908360e01c02179055509260200192600401602081600301049283019260010302611356565b80156113e65782816101000a81549063ffffffff02191690556004016020816003010492830192600103026113b6565b505b5090506113f59190611416565b5090565b5b808211156114125760008160009055506001016113fa565b5090565b5b8082111561143d57600081816101000a81549063ffffffff021916905550600101611417565b509056fe496d706c656d656e746174696f6e733a205f73696720616c7265616479206164646564496d706c656d656e746174696f6e733a205f64656661756c74496d706c656d656e746174696f6e2061646472657373206e6f742076616c6964496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e20616c72656164792061646465642e496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e206e6f742076616c69642e496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e206e6f7420666f756e642e496d706c656d656e746174696f6e733a205f64656661756c74496d706c656d656e746174696f6e2063616e6e6f742062652073616d65a2646970667358221220d42dcb568934728d15f318f76a6028fe848a484b097ea24581f45425fcde152864736f6c63430007000033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063b39c45931161005b578063b39c4593146101e2578063dc9cc64514610216578063ef7e5c7b1461028d578063f0c01b421461030457610088565b806322175a321461008d5780637c16ffc4146100d157806389396dc814610115578063a41098bf146101ae575b600080fd5b6100cf600480360360208110156100a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061039d565b005b610113600480360360208110156100e757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610859565b005b6101576004803603602081101561012b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b82565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561019a57808201518184015260208101905061017f565b505050509050019250505060405180910390f35b6101b6610c5b565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101ea610c7f565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102616004803603602081101561022c57600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610ca3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102d8600480360360208110156102a357600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610d7e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61039b6004803603604081101561031a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561035757600080fd5b82018360208201111561036957600080fd5b8035906020019184602083028401116401000000008311171561038b57600080fd5b9091929391929390505050610df9565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b15801561040357600080fd5b505afa158015610417573d6000803e3d6000fd5b505050506040513d602081101561042d57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610564576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114cd602b913960400191505060405180910390fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501415610600576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114f8602b913960400191505060405180910390fd5b6060600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156106cd57602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841161067a5790505b5050505050905060005b815181101561077a5760008282815181106106ee57fe5b6020026020010151905060016000827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555080806001019150506106d7565b50600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006107c69190611305565b8173ffffffffffffffffffffffffffffffffffffffff167fb7d759e6cdda23e8a1749bce345fc77355b8a22eeaf92c6e4e7257d959c162c7826040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610842578082015181840152602081019050610827565b505050509050019250505060405180910390a25050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b1580156108bf57600080fd5b505afa1580156108d3573d6000803e3d6000fd5b505050506040513d60208110156108e957600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260398152602001806114656039913960400191505060405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610ac5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806115236036913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f3b337225b8d68d037e0c721876335a3832bd08162c943fe5f88e8d428597ca8f60405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6060600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480602002602001604051908101604052809291908181526020018280548015610c4f57602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411610bfc5790505b50505050509050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d545780610d76565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff165b915050919050565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ee97f7f36040518163ffffffff1660e01b815260040160206040518083038186803b158015610e5f57600080fd5b505afa158015610e73573d6000803e3d6000fd5b505050506040513d6020811015610e8957600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610f3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496d706c656d656e746174696f6e733a206e6f742d6d6173746572000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610fc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806114cd602b913960400191505060405180910390fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490501461105b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061149e602f913960400191505060405180910390fd5b60005b8282905081101561123357600083838381811061107757fe5b905060200201357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169050600073ffffffffffffffffffffffffffffffffffffffff1660016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611195576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806114426023913960400191505060405180910390fd5b8460016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050808060010191505061105e565b508181600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020919061128292919061132d565b508273ffffffffffffffffffffffffffffffffffffffff167ff9c512a86be00aaec236065d0a439f064133f367de889c782448c3578a3f30c5838360405180806020018281038252848482818152602001925060200280828437600081840152601f19601f820116905080830192505050935050505060405180910390a2505050565b50805460008255600701600890049060005260206000209081019061132a91906113f9565b50565b828054828255906000526020600020906007016008900481019282156113e85791602002820160005b838211156113b65783357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191683826101000a81548163ffffffff021916908360e01c02179055509260200192600401602081600301049283019260010302611356565b80156113e65782816101000a81549063ffffffff02191690556004016020816003010492830192600103026113b6565b505b5090506113f59190611416565b5090565b5b808211156114125760008160009055506001016113fa565b5090565b5b8082111561143d57600081816101000a81549063ffffffff021916905550600101611417565b509056fe496d706c656d656e746174696f6e733a205f73696720616c7265616479206164646564496d706c656d656e746174696f6e733a205f64656661756c74496d706c656d656e746174696f6e2061646472657373206e6f742076616c6964496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e20616c72656164792061646465642e496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e206e6f742076616c69642e496d706c656d656e746174696f6e733a205f696d706c656d656e746174696f6e206e6f7420666f756e642e496d706c656d656e746174696f6e733a205f64656661756c74496d706c656d656e746174696f6e2063616e6e6f742062652073616d65a2646970667358221220d42dcb568934728d15f318f76a6028fe848a484b097ea24581f45425fcde152864736f6c63430007000033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/status-checks/check.js b/status-checks/check.js index a76d81ae..c0848d77 100644 --- a/status-checks/check.js +++ b/status-checks/check.js @@ -3,13 +3,11 @@ const path = require('path') const forbiddenStrings = ['selfdestruct'] -const getConnectorsList = async () => { +const getConnectorsList = async (connectorsRootsDirs) => { try { const connectors = [] - const connectorsRootsDirs = ['mainnet', 'polygon'] for (let index = 0; index < connectorsRootsDirs.length; index++) { - const root = `contracts/${connectorsRootsDirs[index]}/connectors` - const dirs = [root] + const dirs = [connectorsRootsDirs[index]] while (dirs.length) { const currentDir = dirs.pop() const subs = fs.readdirSync(currentDir, { withFileTypes: true }) @@ -326,9 +324,14 @@ const checkHeadComments = async (connector) => { async function checkMain () { try { + const connectorsRootsDirsDefault = ['mainnet', 'polygon'].map(v=> `contracts/${v}/connectors`) + const customPathArg = process.argv.find(a => a.startsWith('connector=')) + const connectorsRootsDirs = customPathArg + ? [customPathArg.slice(10)] + : connectorsRootsDirsDefault const errors = [] const warnings = [] - const connectors = await getConnectorsList() + const connectors = await getConnectorsList(connectorsRootsDirs) for (let index = 0; index < connectors.length; index++) { const { forbiddenErrors, code } = await checkForbidden(connectors[index].path) connectors[index].code = code diff --git a/status-checks/readme.md b/status-checks/readme.md new file mode 100644 index 00000000..ed376c25 --- /dev/null +++ b/status-checks/readme.md @@ -0,0 +1,7 @@ + +# Check run + +use +`npm run check` +to check `connectors` directory. Use `connector=$` argument to check specific connector: +`npm run check connector=contracts/mainnet/common` diff --git a/test/basic-ERC1155/ERC1155-transfer.js b/test/basic-ERC1155/ERC1155-transfer.js new file mode 100644 index 00000000..cd2f2b12 --- /dev/null +++ b/test/basic-ERC1155/ERC1155-transfer.js @@ -0,0 +1,127 @@ +const { expect } = require("chai"); +const hre = require("hardhat"); +const { web3, deployments, waffle, ethers } = hre; +const { provider, deployContract } = waffle +const {abi: implementationsABI} = require("../../scripts/constant/abi/core/InstaImplementations.json") + +const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") +const buildDSAv2 = require("../../scripts/buildDSAv2") +const encodeSpells = require("../../scripts/encodeSpells.js") +const getMasterSigner = require("../../scripts/getMasterSigner") + +const addresses = require("../../scripts/constant/addresses"); +const abis = require("../../scripts/constant/abis"); +const constants = require("../../scripts/constant/constant"); +const tokens = require("../../scripts/constant/tokens"); + +const connectV2BasicERC1155Artifacts = require("../../artifacts/contracts/mainnet/connectors/basic-ERC1155/main.sol/ConnectV2BasicERC1155.json") +const erc1155Artifacts = require("../../artifacts/@openzeppelin/contracts/token/ERC1155/IERC1155.sol/IERC1155.json") + +const TOKEN_CONTRACT_ADDR = "0x1ca3262009b21F944e6b92a2a88D039D06F1acFa"; +const TOKEN_OWNER_ADDR = "0x1ca3262009b21F944e6b92a2a88D039D06F1acFa"; +const TOKEN_ID = "1"; + +const implementationsMappingAddr = "0xCBA828153d3a85b30B5b912e1f2daCac5816aE9D" + +describe("BASIC-ERC1155", function () { + const connectorName = "BASIC-ERC1155-A" + + let dsaWallet0 + let masterSigner; + let instaConnectorsV2; + let connector; + let nftContract; + let tokenOwner; + let instaImplementationsMapping; + + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [TOKEN_OWNER_ADDR], + }); + + await network.provider.send("hardhat_setBalance", [ + TOKEN_OWNER_ADDR, + "0x1000000000000000", + ]); + + // get tokenOwner + tokenOwner = await ethers.getSigner( + TOKEN_OWNER_ADDR + ); + nftContract = await ethers.getContractAt(erc1155Artifacts.abi, TOKEN_CONTRACT_ADDR) + masterSigner = await getMasterSigner(wallet3) + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + + instaImplementationsMapping = await ethers.getContractAt(implementationsABI, implementationsMappingAddr); + InstaAccountV2DefaultImpl = await ethers.getContractFactory("InstaDefaultImplementation") + instaAccountV2DefaultImpl = await InstaAccountV2DefaultImpl.deploy(addresses.core.instaIndex); + await instaAccountV2DefaultImpl.deployed() + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: connectV2BasicERC1155Artifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!masterSigner.address).to.be.true; + }); + + describe("Implementations", function () { + + it("Should add default implementation to mapping.", async function () { + const tx = await instaImplementationsMapping.connect(masterSigner).setDefaultImplementation(instaAccountV2DefaultImpl.address); + await tx.wait() + expect(await instaImplementationsMapping.defaultImplementation()).to.be.equal(instaAccountV2DefaultImpl.address); + }); + + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(tokenOwner.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + }); + }); + + describe("Main", function () { + it("should deposit successfully", async () => { + console.log("DSA wallet address", dsaWallet0.address) + await nftContract.connect(tokenOwner).setApprovalForAll(dsaWallet0.address, true); + const spells = [ + { + connector: connectorName, + method: "depositERC1155", + args: [ + TOKEN_CONTRACT_ADDR, + TOKEN_ID, + 1, + "0", + "0" + ] + } + ]; + + const tx = await dsaWallet0 + .connect(tokenOwner) + .cast(...encodeSpells(spells), tokenOwner.address); + const receipt = await tx.wait(); + }); + }) +}) diff --git a/test/basic-ERC721/ERC721-transfer.js b/test/basic-ERC721/ERC721-transfer.js new file mode 100644 index 00000000..01a5de0b --- /dev/null +++ b/test/basic-ERC721/ERC721-transfer.js @@ -0,0 +1,126 @@ +const { expect } = require("chai"); +const hre = require("hardhat"); +const { web3, deployments, waffle, ethers } = hre; +const { provider, deployContract } = waffle +const {abi: implementationsABI} = require("../../scripts/constant/abi/core/InstaImplementations.json") + +const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") +const buildDSAv2 = require("../../scripts/buildDSAv2") +const encodeSpells = require("../../scripts/encodeSpells.js") +const getMasterSigner = require("../../scripts/getMasterSigner") + +const addresses = require("../../scripts/constant/addresses"); +const abis = require("../../scripts/constant/abis"); +const constants = require("../../scripts/constant/constant"); +const tokens = require("../../scripts/constant/tokens"); + +const connectV2BasicERC721Artifacts = require("../../artifacts/contracts/mainnet/connectors/basic-ERC721/main.sol/ConnectV2BasicERC721.json") +const erc721Artifacts = require("../../artifacts/@openzeppelin/contracts/token/ERC721/IERC721.sol/IERC721.json") + +const TOKEN_CONTRACT_ADDR = "0x4d695c615a7aacf2d7b9c481b66045bb2457dfde"; +const TOKEN_OWNER_ADDR = "0x8c6b10d42ff08e56133fca0dac75e1931b1fcc23"; +const TOKEN_ID = "38"; + +const implementationsMappingAddr = "0xCBA828153d3a85b30B5b912e1f2daCac5816aE9D" + +describe("BASIC-ERC721", function () { + const connectorName = "BASIC-ERC721-A" + + let dsaWallet0 + let masterSigner; + let instaConnectorsV2; + let connector; + let nftContract; + let tokenOwner; + let instaImplementationsMapping; + + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [TOKEN_OWNER_ADDR], + }); + + await network.provider.send("hardhat_setBalance", [ + TOKEN_OWNER_ADDR, + "0x1000000000000000", + ]); + + // get tokenOwner + tokenOwner = await ethers.getSigner( + TOKEN_OWNER_ADDR + ); + nftContract = await ethers.getContractAt(erc721Artifacts.abi, TOKEN_CONTRACT_ADDR) + masterSigner = await getMasterSigner(wallet3) + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + + instaImplementationsMapping = await ethers.getContractAt(implementationsABI, implementationsMappingAddr); + InstaAccountV2DefaultImpl = await ethers.getContractFactory("InstaDefaultImplementation") + instaAccountV2DefaultImpl = await InstaAccountV2DefaultImpl.deploy(addresses.core.instaIndex); + await instaAccountV2DefaultImpl.deployed() + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: connectV2BasicERC721Artifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!masterSigner.address).to.be.true; + }); + + describe("Implementations", function () { + + it("Should add default implementation to mapping.", async function () { + const tx = await instaImplementationsMapping.connect(masterSigner).setDefaultImplementation(instaAccountV2DefaultImpl.address); + await tx.wait() + expect(await instaImplementationsMapping.defaultImplementation()).to.be.equal(instaAccountV2DefaultImpl.address); + }); + + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(tokenOwner.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + }); + }); + + describe("Main", function () { + it("should deposit successfully", async () => { + console.log("DSA wallet address", dsaWallet0.address) + await nftContract.connect(tokenOwner).setApprovalForAll(dsaWallet0.address, true); + const spells = [ + { + connector: connectorName, + method: "depositERC721", + args: [ + TOKEN_CONTRACT_ADDR, + TOKEN_ID, + "0", + "0" + ] + } + ]; + + const tx = await dsaWallet0 + .connect(tokenOwner) + .cast(...encodeSpells(spells), tokenOwner.address); + const receipt = await tx.wait(); + }); + }) +}) diff --git a/test/yearn/yearn.test.js b/test/yearn/yearn.test.js new file mode 100644 index 00000000..409161b0 --- /dev/null +++ b/test/yearn/yearn.test.js @@ -0,0 +1,142 @@ +const { expect } = require("chai"); +const hre = require("hardhat"); +const { waffle, ethers } = hre; +const { provider } = waffle + +const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js") +const buildDSAv2 = require("../../scripts/buildDSAv2") +const encodeSpells = require("../../scripts/encodeSpells.js") +const getMasterSigner = require("../../scripts/getMasterSigner") + +const tokens = require("../../scripts/constant/tokens"); +const addresses = require("../../scripts/constant/addresses"); +const abis = require("../../scripts/constant/abis"); +const connectV2YearnArtifacts = require("../../artifacts/contracts/mainnet/connectors/yearn_v2/main.sol/ConnectV2YearnV2.json") + +const toBytes32 = (bn) => { + return ethers.utils.hexlify(ethers.utils.zeroPad(bn.toHexString(), 32)); +}; +const setStorageAt = async (address, index, value) => { + await ethers.provider.send("hardhat_setStorageAt", [address, index, value]); + await ethers.provider.send("evm_mine", []); // Just mines to the next block +}; + +describe("Yearn", function () { + const connectorName = "YEARN-TEST-A" + + let dsaWallet0 + let masterSigner; + let instaConnectorsV2; + let connector; + + const wallets = provider.getWallets() + const [wallet0, wallet1, wallet2, wallet3] = wallets + before(async () => { + masterSigner = await getMasterSigner(wallet3) + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: connectV2YearnArtifacts, + signer: masterSigner, + connectors: instaConnectorsV2 + }) + console.log("Connector address", connector.address) + }) + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!masterSigner.address).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(wallet0.address) + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + }); + }); + + describe("Main", function () { + + it("Should increase the DAI balance to 100 DAI", async function () { + const DAI = new ethers.Contract(tokens.dai.address, abis.basic.erc20, ethers.provider); + const DAI_SLOT = 2; + const locallyManipulatedBalance = ethers.utils.parseEther("100"); + + // Get storage slot index + const index = ethers.utils.solidityKeccak256( + ["uint256", "uint256"], + [dsaWallet0.address, DAI_SLOT] + ); + // Manipulate local balance (needs to be bytes32 string) + await setStorageAt( + tokens.dai.address, + index.toString(), + toBytes32(locallyManipulatedBalance).toString() + ); + + // Get DAI balance + const balance = await DAI.balanceOf(dsaWallet0.address); + expect(await ethers.BigNumber.from(balance).eq(ethers.utils.parseEther("100"))); + }); + + it("Should deposit and withdraw 50 DAI in/out the Yearn Vault", async function () { + const DAI = new ethers.Contract(tokens.dai.address, abis.basic.erc20, ethers.provider); + const DAI_VAULT = '0xdA816459F1AB5631232FE5e97a05BBBb94970c95'; + const amount = ethers.utils.parseEther("50") // 50 DAI + const setId = "132456"; + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [DAI_VAULT, amount, 0, setId] + }, + { + connector: connectorName, + method: "withdraw", + args: [DAI_VAULT, amount, setId, 0] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address); + await tx.wait(); + + // Get DAI balance + const balance = await DAI.balanceOf(dsaWallet0.address); + expect(await ethers.BigNumber.from(balance).eq(ethers.utils.parseEther("100"))); + }); + + it("Should deposit 70 DAI in the Yearn Vault", async function () { + const DAI_VAULT = '0xdA816459F1AB5631232FE5e97a05BBBb94970c95'; + const DAI = new ethers.Contract(tokens.dai.address, abis.basic.erc20, ethers.provider); + const YVDAI = new ethers.Contract(DAI_VAULT, abis.basic.erc20, ethers.provider); + const amount = ethers.utils.parseEther("70") // 70 DAI + const setId = "568445"; + const spells = [ + { + connector: connectorName, + method: "deposit", + args: [DAI_VAULT, amount, 0, setId] + } + ] + + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet0.address); + await tx.wait(); + + // Get DAI balance + const yvDAIBalance = await YVDAI.balanceOf(dsaWallet0.address); + const daiBalance = await DAI.balanceOf(dsaWallet0.address); + const correctDaiBalance = await ethers.BigNumber.from(daiBalance).eq(ethers.utils.parseEther("30")); + const correctYVDaiBalance = await ethers.BigNumber.from(yvDAIBalance).lte(ethers.utils.parseEther("70")); + expect(correctDaiBalance && correctYVDaiBalance); + }); + }) +})