Add quoter example contract for decimals translation

This commit is contained in:
lash
2023-08-03 14:53:30 +01:00
parent af059d24a7
commit 5a1114ae55
9 changed files with 323 additions and 0 deletions

View File

@@ -0,0 +1 @@
608060405234801561001057600080fd5b506108ed806100206000396000f3fe608060405234801561001057600080fd5b5060043610610048576000357c010000000000000000000000000000000000000000000000000000000090048063dbb21d401461004d575b600080fd5b6100676004803603810190610062919061044b565b61007d565b60405161007491906104ad565b60405180910390f35b600080600080600060608873ffffffffffffffffffffffffffffffffffffffff166040516024016040516020818303038152906040527f313ce567000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161012e9190610539565b6000604051808303816000865af19150503d806000811461016b576040519150601f19603f3d011682016040523d82523d6000602084013e610170565b606091505b508092508193505050816101b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101b0906105ad565b60405180910390fd5b808060200190518101906101cd9190610606565b94508773ffffffffffffffffffffffffffffffffffffffff166040516024016040516020818303038152906040527f313ce567000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516102769190610539565b6000604051808303816000865af19150503d80600081146102b3576040519150601f19603f3d011682016040523d82523d6000602084013e6102b8565b606091505b50809250819350505081610301576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102f8906105ad565b60405180910390fd5b808060200190518101906103159190610606565b93508460ff168460ff16036103315786955050505050506103ab565b8460ff168460ff16111561037757848461034b9190610662565b60ff16925082600a61035d91906107ca565b9250828761036b9190610844565b955050505050506103ab565b83856103839190610662565b60ff16925082600a61039591906107ca565b925082876103a39190610875565b955050505050505b9392505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006103e2826103b7565b9050919050565b6103f2816103d7565b81146103fd57600080fd5b50565b60008135905061040f816103e9565b92915050565b6000819050919050565b61042881610415565b811461043357600080fd5b50565b6000813590506104458161041f565b92915050565b600080600060608486031215610464576104636103b2565b5b600061047286828701610400565b935050602061048386828701610400565b925050604061049486828701610436565b9150509250925092565b6104a781610415565b82525050565b60006020820190506104c2600083018461049e565b92915050565b600081519050919050565b600081905092915050565b60005b838110156104fc5780820151818401526020810190506104e1565b60008484015250505050565b6000610513826104c8565b61051d81856104d3565b935061052d8185602086016104de565b80840191505092915050565b60006105458284610508565b915081905092915050565b600082825260208201905092915050565b7f4552525f544f4b454e0000000000000000000000000000000000000000000000600082015250565b6000610597600983610550565b91506105a282610561565b602082019050919050565b600060208201905081810360008301526105c68161058a565b9050919050565b600060ff82169050919050565b6105e3816105cd565b81146105ee57600080fd5b50565b600081519050610600816105da565b92915050565b60006020828403121561061c5761061b6103b2565b5b600061062a848285016105f1565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061066d826105cd565b9150610678836105cd565b9250828203905060ff81111561069157610690610633565b5b92915050565b6000600282049050919050565b6000808291508390505b60018511156106ee578086048111156106ca576106c9610633565b5b60018516156106d95780820291505b80810290506106e785610697565b94506106ae565b94509492505050565b60008261070757600190506107c3565b8161071557600090506107c3565b816001811461072b576002811461073557610764565b60019150506107c3565b60ff84111561074757610746610633565b5b8360020a91508482111561075e5761075d610633565b5b506107c3565b5060208310610133831016604e8410600b84101617156107995782820a90508381111561079457610793610633565b5b6107c3565b6107a684848460016106a4565b925090508184048111156107bd576107bc610633565b5b81810290505b9392505050565b60006107d582610415565b91506107e083610415565b925061080d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846106f7565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061084f82610415565b915061085a83610415565b92508261086a57610869610815565b5b828204905092915050565b600061088082610415565b915061088b83610415565b925082820261089981610415565b915082820484148315176108b0576108af610633565b5b509291505056fea26469706673582212201acbf661561a2312e8b64602d749a5af7f05876881796fccdca1072b6ee3bf6664736f6c63430008130033

View File

@@ -0,0 +1 @@
[{"inputs":[{"internalType":"address","name":"_outToken","type":"address"},{"internalType":"address","name":"_inToken","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"valueFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

View File

@@ -0,0 +1 @@
{"compiler":{"version":"0.8.19+commit.7dd6d404"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"_outToken","type":"address"},{"internalType":"address","name":"_inToken","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"valueFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"compilationTarget":{"DecimalQuote.sol":"DecimalQuote"},"evmVersion":"byzantium","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"DecimalQuote.sol":{"keccak256":"0x9e5bc44ea381d6794c6bc992b8cee0b68fb700ab0ad888e5cec390d2261fd5f2","license":"AGPL-3.0-or-later","urls":["bzz-raw://a1d11d7ee1286203963eef4846272465fc7abdeb5c4e054f84fe9dada91b10ee","dweb:/ipfs/QmZQDttgfUBAJxxRpxW8JkwkWi61hNQ79NNrWD64Ak92vw"]}},"version":1}

View File

@@ -0,0 +1,98 @@
# standard imports
import logging
import os
import enum
# external imports
from chainlib.eth.constant import ZERO_ADDRESS
from chainlib.eth.constant import ZERO_CONTENT
from chainlib.eth.contract import (
ABIContractEncoder,
ABIContractDecoder,
ABIContractType,
abi_decode_single,
)
from chainlib.eth.jsonrpc import to_blockheight_param
from chainlib.eth.error import RequestMismatchException
from chainlib.eth.tx import (
TxFactory,
TxFormat,
)
from chainlib.jsonrpc import JSONRPCRequest
from chainlib.block import BlockSpec
from hexathon import (
add_0x,
strip_0x,
)
from chainlib.eth.cli.encode import CLIEncoder
# local imports
from erc20_pool.data import data_dir
logg = logging.getLogger()
class DecimalQuote(TxFactory):
__abi = None
__bytecode = None
def constructor(self, sender_address, tx_format=TxFormat.JSONRPC, version=None):
code = self.cargs(version=version)
tx = self.template(sender_address, None, use_nonce=True)
tx = self.set_code(tx, code)
return self.finalize(tx, tx_format)
@staticmethod
def cargs(version=None):
code = DecimalQuote.bytecode(version=version)
enc = ABIContractEncoder()
args = enc.get()
code += args
logg.debug('constructor code: ' + args)
return code
@staticmethod
def gas(code=None):
return 4000000
@staticmethod
def abi():
if DecimalQuote.__abi == None:
f = open(os.path.join(data_dir, 'DecimalQuote.json'), 'r')
DecimalQuote.__abi = json.load(f)
f.close()
return DecimalQuote.__abi
@staticmethod
def bytecode(version=None):
if DecimalQuote.__bytecode == None:
f = open(os.path.join(data_dir, 'DecimalQuote.bin'))
DecimalQuote.__bytecode = f.read()
f.close()
return DecimalQuote.__bytecode
def value_for(self, contract_address, token_address_out, token_address_in, value_in, sender_address=ZERO_ADDRESS, id_generator=None):
j = JSONRPCRequest(id_generator)
o = j.template()
o['method'] = 'eth_call'
enc = ABIContractEncoder()
enc.method('valueFor')
enc.typ(ABIContractType.ADDRESS)
enc.typ(ABIContractType.ADDRESS)
enc.typ(ABIContractType.UINT256)
enc.address(token_address_out)
enc.address(token_address_in)
enc.uint256(value_in)
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

View File

@@ -0,0 +1,37 @@
# standard imports
import logging
import time
# external imports
from chainlib.eth.unittest.ethtester import EthTesterCase
from chainlib.connection import RPCConnection
from chainlib.eth.nonce import RPCNonceOracle
from chainlib.eth.tx import receipt
from chainlib.eth.address import to_checksum_address
from giftable_erc20_token.unittest import TestGiftableToken
from eth_erc20 import ERC20
from chainlib.eth.block import block_latest
from eth_accounts_index.unittest import TestAccountsIndex
from eth_accounts_index.registry import AccountRegistry
from giftable_erc20_token import GiftableToken
from erc20_limiter.unittest import TestLimiter
# local imports
from erc20_pool.quote import DecimalQuote
logg = logging.getLogger(__name__)
class TestDecimalQuote(EthTesterCase):
def setUp(self):
super(TestDecimalQuote, self).setUp()
self.conn = RPCConnection.connect(self.chain_spec, 'default')
nonce_oracle = RPCNonceOracle(self.accounts[0], conn=self.conn)
c = DecimalQuote(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
(tx_hash, o) = c.constructor(self.accounts[0])
self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
self.quoter_address = to_checksum_address(r['contract_address'])
logg.debug('published quoter {}'.format(self.quoter_address))

View File

@@ -0,0 +1,61 @@
# standard imports
import unittest
import logging
import os
from chainlib.eth.nonce import RPCNonceOracle
from chainlib.eth.tx import receipt
from chainlib.eth.block import block_latest
from hexathon import same as same_hex
from eth_erc20 import ERC20
from giftable_erc20_token import GiftableToken
from erc20_limiter import Limiter
# local imports
from erc20_pool.quote import DecimalQuote
from erc20_pool.unittest.quote import TestDecimalQuote
logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
class TestQuote(TestDecimalQuote):
def setUp(self):
super(TestQuote, self).setUp()
self.tokens = {}
self.publish_token('Foo token', 'FOO', 14)
self.publish_token('Bar token', 'BAR', 18)
self.publish_token('Baz token', 'BAZ', 11)
def publish_token(self, name, symbol, decimals):
nonce_oracle = RPCNonceOracle(self.accounts[0], conn=self.conn)
c = GiftableToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle)
self.symbol = name
self.name = symbol
self.decimals = decimals
(tx_hash, o) = c.constructor(self.accounts[0], self.name, self.symbol, self.decimals, expire=0)
self.rpc.do(o)
o = receipt(tx_hash)
r = self.rpc.do(o)
self.assertEqual(r['status'], 1)
address = r['contract_address']
logg.debug('published "{}" ("{}") on address {} with hash {}'.format(name, symbol, address, tx_hash))
self.tokens[symbol] = address
def test_quote(self):
c = DecimalQuote(self.chain_spec)
o = c.value_for(self.quoter_address, self.tokens['FOO'], self.tokens['FOO'], 10**18, sender_address=self.accounts[0])
r = self.rpc.do(o)
self.assertEqual(int(r, 16), 10**18)
o = c.value_for(self.quoter_address, self.tokens['FOO'], self.tokens['BAR'], 10**18, sender_address=self.accounts[0])
r = self.rpc.do(o)
self.assertEqual(int(r, 16), 10**14)
o = c.value_for(self.quoter_address, self.tokens['FOO'], self.tokens['BAZ'], 10**18, sender_address=self.accounts[0])
r = self.rpc.do(o)
self.assertEqual(int(r, 16), 10**21)
if __name__ == '__main__':
unittest.main()