commit d1680b60e70e0449e51e68d8eb18f41c6d176313
parent ccc616a1dc8505f37406722a4a11a554ed7075e1
Author: lash <dev@holbrook.no>
Date: Fri, 28 Jul 2023 10:47:00 +0100
Make limitOf external function, expose unittest fixture
Diffstat:
6 files changed, 79 insertions(+), 11 deletions(-)
diff --git a/python/erc20_limiter/data/Limiter.bin b/python/erc20_limiter/data/Limiter.bin
@@ -1 +1 @@
-608060405234801561001057600080fd5b506102c6806100206000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c010000000000000000000000000000000000000000000000000000000090048063237786131461005857806336db43b514610088575b600080fd5b610072600480360381019061006d91906101b0565b6100a4565b60405161007f9190610209565b60405180910390f35b6100a2600480360381019061009d9190610250565b6100c9565b005b6000602052816000526040600020602052806000526040600020600091509150505481565b806000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061017d82610152565b9050919050565b61018d81610172565b811461019857600080fd5b50565b6000813590506101aa81610184565b92915050565b600080604083850312156101c7576101c661014d565b5b60006101d58582860161019b565b92505060206101e68582860161019b565b9150509250929050565b6000819050919050565b610203816101f0565b82525050565b600060208201905061021e60008301846101fa565b92915050565b61022d816101f0565b811461023857600080fd5b50565b60008135905061024a81610224565b92915050565b600080604083850312156102675761026661014d565b5b60006102758582860161019b565b92505060206102868582860161023b565b915050925092905056fea2646970667358221220b0b99ecbbe087d46a73d112695aeff90259e3319f10106bab0b8330733dbea4364736f6c63430008130033
-\ No newline at end of file
+608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610931806100606000396000f3fe608060405234801561001057600080fd5b506004361061007f576000357c01000000000000000000000000000000000000000000000000000000009004806301ffc9a71461008457806323778613146100b457806336db43b5146100e45780638da5cb5b14610100578063bdd554401461011e578063f2fde38b1461013a575b600080fd5b61009e60048036038101906100999190610633565b61016a565b6040516100ab919061067b565b60405180910390f35b6100ce60048036038101906100c991906106f4565b61021a565b6040516100db919061074d565b60405180910390f35b6100fe60048036038101906100f99190610794565b6102a1565b005b610108610326565b60405161011591906107e3565b60405180910390f35b610138600480360381019061013391906107fe565b61034a565b005b610154600480360381019061014f9190610851565b610494565b604051610161919061067b565b60405180910390f35b60006301ffc9a77c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036101be5760019050610215565b639493f8b27c010000000000000000000000000000000000000000000000000000000002827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916036102105760019050610215565b600090505b919050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806103cf57508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61040e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610405906108db565b60405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505050565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104ef57600080fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050826000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36001915050919050565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610610816105db565b811461061b57600080fd5b50565b60008135905061062d81610607565b92915050565b600060208284031215610649576106486105d6565b5b60006106578482850161061e565b91505092915050565b60008115159050919050565b61067581610660565b82525050565b6000602082019050610690600083018461066c565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006106c182610696565b9050919050565b6106d1816106b6565b81146106dc57600080fd5b50565b6000813590506106ee816106c8565b92915050565b6000806040838503121561070b5761070a6105d6565b5b6000610719858286016106df565b925050602061072a858286016106df565b9150509250929050565b6000819050919050565b61074781610734565b82525050565b6000602082019050610762600083018461073e565b92915050565b61077181610734565b811461077c57600080fd5b50565b60008135905061078e81610768565b92915050565b600080604083850312156107ab576107aa6105d6565b5b60006107b9858286016106df565b92505060206107ca8582860161077f565b9150509250929050565b6107dd816106b6565b82525050565b60006020820190506107f860008301846107d4565b92915050565b600080600060608486031215610817576108166105d6565b5b6000610825868287016106df565b9350506020610836868287016106df565b92505060406108478682870161077f565b9150509250925092565b600060208284031215610867576108666105d6565b5b6000610875848285016106df565b91505092915050565b600082825260208201905092915050565b7f4552525f41585800000000000000000000000000000000000000000000000000600082015250565b60006108c560078361087e565b91506108d08261088f565b602082019050919050565b600060208201905081810360008301526108f4816108b8565b905091905056fea2646970667358221220637537cee91db8d40743b879190b927cde6e34eee8a9524863365ce11ec024c664736f6c63430008130033
+\ No newline at end of file
diff --git a/python/erc20_limiter/data/Limiter.json b/python/erc20_limiter/data/Limiter.json
@@ -1 +1 @@
-[{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"limitOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"setLimit","outputs":[],"stateMutability":"nonpayable","type":"function"}]
+[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_holder","type":"address"}],"name":"limitOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"setLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_holder","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"setLimitFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_sum","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
diff --git a/python/erc20_limiter/data/Limiter.metadata.json b/python/erc20_limiter/data/Limiter.metadata.json
@@ -1 +1 @@
-{"compiler":{"version":"0.8.19+commit.7dd6d404"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"limitOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"setLimit","outputs":[],"stateMutability":"nonpayable","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"Limiter.sol":"Limiter"},"evmVersion":"byzantium","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"Limiter.sol":{"keccak256":"0x24351d76034fded7d12ba485309035752a6c960c49e0079c3ad22eaeb11dad9d","license":"AGPL-3.0-or-later","urls":["bzz-raw://2982f178296a2675687b4b65110529f439cd2bcb837579e9658bbf913a978d0b","dweb:/ipfs/Qmf6g95sC1RaRZ6DJ6w2yDnBRoDPFKGid73yefj1pv4jsM"]}},"version":1}
+{"compiler":{"version":"0.8.19+commit.7dd6d404"},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_holder","type":"address"}],"name":"limitOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"setLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_holder","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"setLimitFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_sum","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"Limiter.sol":"Limiter"},"evmVersion":"byzantium","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"Limiter.sol":{"keccak256":"0x5d2efe5fb5477abcc3f9ae9cb2f89caa2138ae71308f74e7860fea85999fd7c5","license":"AGPL-3.0-or-later","urls":["bzz-raw://3cc9ed399ceab3c64b147cafaa577351a943a442ab3d7fece036444c88d3800e","dweb:/ipfs/Qmd41uw2HGfXd1AvKGQAHsikjvopRPLidXBDQrx5zz6igT"]}},"version":1}
diff --git a/python/erc20_limiter/limiter.py b/python/erc20_limiter/limiter.py
@@ -77,15 +77,41 @@ class Limiter(TxFactory):
return Limiter.__bytecode
- def set_limit(self, contract_address, sender_address, token_address, limit, tx_format=TxFormat.JSONRPC, id_generator=None):
+ def set_limit(self, contract_address, sender_address, token_address, limit, holder_address=None, tx_format=TxFormat.JSONRPC, id_generator=None):
enc = ABIContractEncoder()
- enc.method('setLimit')
+ if holder_address != None:
+ enc.method('setLimitFor')
enc.typ(ABIContractType.ADDRESS)
+ if holder_address != None:
+ enc.typ(ABIContractType.ADDRESS)
enc.typ(ABIContractType.UINT256)
enc.address(token_address)
+ if holder_address != None:
+ enc.address(holder_address)
enc.uint256(limit)
data = add_0x(enc.get())
tx = self.template(sender_address, contract_address, use_nonce=True)
tx = self.set_code(tx, data)
tx = self.finalize(tx, tx_format, id_generator=id_generator)
return tx
+
+
+ def limit_of(self, contract_address, token_address, holder_address, sender_address=ZERO_ADDRESS, id_generator=None):
+ j = JSONRPCRequest(id_generator)
+ o = j.template()
+ o['method'] = 'eth_call'
+ enc = ABIContractEncoder()
+ enc.method('limitOf')
+ enc.typ(ABIContractType.ADDRESS)
+ enc.typ(ABIContractType.ADDRESS)
+ enc.address(token_address)
+ enc.address(holder_address)
+ data = add_0x(enc.get())
+ tx = self.template(sender_address, contract_address)
+ tx = self.set_code(tx, data)
+ o['params'].append(self.normalize(tx))
+ o['params'].append('latest')
+ o = j.finalize(o)
+ return o
+
+
diff --git a/python/erc20_limiter/unittest/base.py b/python/erc20_limiter/unittest/base.py
@@ -20,7 +20,7 @@ class TestLimiter(EthTesterCase):
def setUp(self):
super(TestLimiter, self).setUp()
self.conn = RPCConnection.connect(self.chain_spec, 'default')
- self.publish_limiter()
+ self.address = self.publish_limiter()
def publish_limiter(self):
@@ -31,5 +31,6 @@ class TestLimiter(EthTesterCase):
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
- self.address = to_checksum_address(r['contract_address'])
- logg.debug('published limiter on address {} with hash {}'.format(self.address, tx_hash))
+ address = to_checksum_address(r['contract_address'])
+ logg.debug('published limiter on address {} with hash {}'.format(address, tx_hash))
+ return address
diff --git a/solidity/Limiter.sol b/solidity/Limiter.sol
@@ -6,9 +6,50 @@ pragma solidity ^0.8.0;
// Description: Registry of allowed ERC20 balance limits per-token and per-holder.
contract Limiter {
- mapping ( address => mapping ( address => uint256 ) ) public limitOf;
+ address public owner;
+
+ mapping ( address => mapping ( address => uint256 ) ) limit;
+
+ // EIP173
+ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // EIP173
+
+ constructor() {
+ owner = msg.sender;
+ }
+
+ function limitOf(address _token, address _holder) public view returns (uint256) {
+ return limit[_token][_holder];
+ }
function setLimit(address _token, uint256 _value) public {
- limitOf[_token][msg.sender] = _value;
+ limit[_token][msg.sender] = _value;
+ }
+
+ function setLimitFor(address _token, address _holder, uint256 _value) public {
+ require(msg.sender == owner || msg.sender == _holder, 'ERR_AXX');
+ limit[_token][_holder] = _value;
+ }
+
+ // Implements EIP173
+ function transferOwnership(address _newOwner) public returns (bool) {
+ address oldOwner;
+
+ require(msg.sender == owner);
+ oldOwner = owner;
+ owner = _newOwner;
+
+ emit OwnershipTransferred(oldOwner, owner);
+ return true;
+ }
+
+ // Implements EIP165
+ function supportsInterface(bytes4 _sum) public pure returns (bool) {
+ if (_sum == 0x01ffc9a7) { // ERC165
+ return true;
+ }
+ if (_sum == 0x9493f8b2) { // ERC173
+ return true;
+ }
+ return false;
}
}