accounts-index

Accounts index evm contract tooling with permissioned writes
Log | Files | Refs

commit 9336d813ed573dda101e4bd2e0528ab34457f697
Author: nolash <dev@holbrook.no>
Date:   Fri, 13 Nov 2020 18:33:39 +0100

Initial commit

Diffstat:
Aregistry.abi.json | 1+
Aregistry.bin | 2++
Aregistry.sol | 36++++++++++++++++++++++++++++++++++++
Atest.py | 42++++++++++++++++++++++++++++++++++++++++++
4 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/registry.abi.json b/registry.abi.json @@ -0,0 +1 @@ +[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addedAccount","type":"address"},{"indexed":true,"internalType":"uint256","name":"accountIndex","type":"uint256"}],"name":"AccountAdded","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"accounts","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accountsIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_writer","type":"address"}],"name":"addWriter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"count","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_writer","type":"address"}],"name":"deleteWriter","outputs":[],"stateMutability":"nonpayable","type":"function"}] diff --git a/registry.bin b/registry.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5033600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061054f806100616000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806306661abd146100675780630a3b0a4f146100855780634c2ebc6b146100c95780635ae06f7e14610121578063da2824a814610165578063f2a40db8146101a9575b600080fd5b61006f610201565b6040518082815260200191505060405180910390f35b6100c76004803603602081101561009b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610207565b005b61010b600480360360208110156100df57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610364565b6040518082815260200191505060405180910390f35b6101636004803603602081101561013757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061037c565b005b6101a76004803603602081101561017b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610428565b005b6101d5600480360360208110156101bf57600080fd5b81019080803590602001909291905050506104dd565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60025481565b600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1661025d57600080fd5b6000819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600254600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506002600081548092919060010191905055506001600254038173ffffffffffffffffffffffffffffffffffffffff167f5ed3bdd47b9af629827a8d129aa39c870b10c03f0153fe9ddb8e84b665061acd60405160405180910390a350565b60016020528060005260406000206000915090505481565b3373ffffffffffffffffffffffffffffffffffffffff16600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103d657600080fd5b600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff021916905550565b3373ffffffffffffffffffffffffffffffffffffffff16600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461048257600080fd5b6001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600081815481106104ea57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fea2646970667358221220d0c43ebb44ba788ac3723dd1aa1293f073f92c8f6e68a8dd975553f67976555264736f6c63430007030033 +\ No newline at end of file diff --git a/registry.sol b/registry.sol @@ -0,0 +1,36 @@ +pragma solidity ^0.7.3; + +// SPDX-License-Identifier: GPL-3.0-or-later + +contract CustodialAccountIndex { + + address[] public accounts; + mapping(address => uint256) public accountsIndex; + uint256 public count; + mapping(address => bool) writers; + address owner; + + event AccountAdded(address indexed addedAccount, uint256 indexed accountIndex); + + constructor() { + owner = msg.sender; + } + + function addWriter(address _writer) public { + require(owner == msg.sender); + writers[_writer] = true; + } + + function deleteWriter(address _writer) public { + require(owner == msg.sender); + delete writers[_writer]; + } + + function add(address _account) public { + require(writers[msg.sender]); + accounts.push(_account); + accountsIndex[_account] = count; + count++; + emit AccountAdded(_account, count-1); + } +} diff --git a/test.py b/test.py @@ -0,0 +1,42 @@ +import web3 +import eth_tester +import json + + +eth_params = eth_tester.backends.pyevm.main.get_default_genesis_params({ + 'gas_limit': 9000000, + }) +backend = eth_tester.PyEVMBackend(eth_params) +instance = eth_tester.EthereumTester(backend) +provider = web3.Web3.EthereumTesterProvider(instance) +w3 = web3.Web3(provider) + + +f = open('registry.bin', 'r') +bytecode = f.read() +f.close() + +f = open('registry.abi.json', 'r') +abi = json.load(f) +f.close() + +c = w3.eth.contract(abi=abi, bytecode=bytecode) +tx_hash = c.constructor().transact({'from': w3.eth.accounts[0]}) + +r = w3.eth.getTransactionReceipt(tx_hash) + +c = w3.eth.contract(abi=abi, address=r.contractAddress) +fail = False +try: + c.functions.add(w3.eth.accounts[2]).transact({'from': w3.eth.accounts[1]}) +except: + fail = True +assert fail + +c.functions.addWriter(w3.eth.accounts[1]).transact({'from': w3.eth.accounts[0]}) +c.functions.add(w3.eth.accounts[2]).transact({'from': w3.eth.accounts[1]}) +c.functions.add(w3.eth.accounts[3]).transact({'from': w3.eth.accounts[1]}) + +assert c.functions.count().call() == 2 +assert c.functions.accountsIndex(w3.eth.accounts[3]).call() == 1 +assert c.functions.accounts(1).call() == w3.eth.accounts[3]