class ProxyRegistry(Contract): """A client for the `ProxyRegistry` contract. Ref. <https://github.com/makerdao/proxy-registry/blob/master/src/ProxyRegistry.sol> """ abi = Contract._load_abi(__name__, 'abi/ProxyRegistry.abi') bin = Contract._load_bin(__name__, 'abi/ProxyRegistry.bin') def __init__(self, web3: Web3, address: Address): assert isinstance(web3, Web3) assert isinstance(address, Address) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) def build(self, owner: Address) -> Transact: assert isinstance(owner, Address) return Transact(self, self.web3, self.abi, self.address, self._contract, 'build(address)', [owner.address]) def proxies(self, owner: Address) -> Address: assert isinstance(owner, Address) return Address(self._contract.functions.proxies(owner.address).call()) def __repr__(self): return f"ProxyRegistry('{self.address}')"
class DSPause(Contract): """A client for the `DSPause` contract, which schedules function calls after a predefined delay. You can find the source code of the `DSPause` contract here: <https://github.com/dapphub/ds-pause>. Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `DSPause` contract. """ class Plan: def __init__(self, usr: Address, fax: bytes, eta: datetime): """Creates a plan to be executed later. Args: usr: Address of the caller fax: Identifies the calldata eta: Identifies the earliest time of execution """ assert isinstance(usr, Address) assert isinstance(fax, bytes) assert isinstance(eta, datetime.datetime) self.usr = usr self.fax = fax self.eta = eta.timestamp() abi = Contract._load_abi(__name__, 'abi/DSPause.abi') bin = Contract._load_bin(__name__, 'abi/DSPause.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) @staticmethod def deploy(web3: Web3, delay: int, owner: Address, ds_auth: DSAuth): return DSPause(web3=web3, address=Contract._deploy(web3, DSPause.abi, DSPause.bin, [delay, owner.address, ds_auth.address.address])) # TODO: Awaiting updated ABI/BIN from dss-deploy # def plot(self, plan: Plan): # return self._transact(plan, "plot") def drop(self, plan: Plan): return self._transact(plan, "drop") def exec(self, plan: Plan) -> Transact: return self._transact(plan, "exec") def _transact(self, plan: Plan, function_name: str) -> Transact: assert isinstance(plan, DSPause.Plan) assert isinstance(function_name, str) return Transact(self, self.web3, self.abi, self.address, self._contract, function_name, [plan.usr.address, plan.fax, int(plan.eta)])
class DSAuth(Contract): abi = Contract._load_abi(__name__, 'abi/DSAuth.abi') bin = Contract._load_bin(__name__, 'abi/DSAuth.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) @staticmethod def deploy(web3: Web3): return DSAuth(web3=web3, address=Contract._deploy(web3, DSAuth.abi, DSAuth.bin, [])) def get_owner(self) -> Address: return Address(self._contract.call().owner()) def set_owner(self, owner: Address) -> Transact: assert isinstance(owner, Address) return Transact(self, self.web3, self.abi, self.address, self._contract, "setOwner", [owner.address]) def set_authority(self, ds_authority: Address): assert isinstance(ds_authority, Address) return Transact(self, self.web3, self.abi, self.address, self._contract, "setAuthority", [ds_authority.address])
class OSM(Contract): """A client for the `OSM` contract. You can find the source code of the `OSM` contract here: <https://github.com/makerdao/osm>. Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `OSM` contract. """ abi = Contract._load_abi(__name__, 'abi/OSM.abi') bin = Contract._load_bin(__name__, 'abi/OSM.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) def poke(self) -> Transact: return Transact(self, self.web3, self.abi, self.address, self._contract, 'poke', []) def __repr__(self): return f"OSM('{self.address}')"
class GemVat(Contract): """A client for the `GemMove` contract. Ref. <https://github.com/makerdao/dss/blob/master/src/move.sol#L25> """ abi = Contract._load_abi(__name__, 'abi/GemMove.abi') bin = Contract._load_bin(__name__, 'abi/GemMove.bin') def __init__(self, web3: Web3, address: Address): assert isinstance(web3, Web3) assert isinstance(address, Address) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) @classmethod def deploy(cls, web3: Web3, vat: Address, ilk: Ilk, gem: Address): return cls( web3=web3, address=Contract._deploy(web3, cls.abi, cls.bin, [vat.address, ilk.toBytes()])) def ilk(self): return Ilk.fromBytes(self._contract.call().ilk())
class OasisMockPriceOracle(Contract): """A mock price Oracle for deploying Oasis MatchingMarket contract""" abi = Contract._load_abi(__name__, 'abi/OasisMockPriceOracle.abi') bin = Contract._load_bin(__name__, 'abi/OasisMockPriceOracle.bin') def __init__(self, web3: Web3, address: Address): assert(isinstance(web3, Web3)) assert(isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) @staticmethod def deploy(web3: Web3): return OasisMockPriceOracle(web3=web3, address=Contract._deploy(web3, OasisMockPriceOracle.abi, OasisMockPriceOracle.bin, [])) def set_price(self, price: Wad): assert isinstance(price, Wad) return Transact(self, self.web3, self.abi, self.address, self._contract, 'setPrice', [price.value]) def __eq__(self, other): return self.address == other.address def __repr__(self): return f"OasisMockPriceOracle('{self.address}')"
class DSVault(Contract): """A client for the `DSVault` contract. You can find the source code of the `DSVault` contract here: <https://github.com/dapphub/ds-vault>. Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `DSVault` contract. """ abi = Contract._load_abi(__name__, 'abi/DSVault.abi') bin = Contract._load_bin(__name__, 'abi/DSVault.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) @staticmethod def deploy(web3: Web3): """Deploy a new instance of the `DSVault` contract. Args: web3: An instance of `Web` from `web3.py`. Returns: A `DSVault` class instance. """ return DSVault(web3=web3, address=Contract._deploy(web3, DSVault.abi, DSVault.bin, [])) def authority(self) -> Address: """Return the current `authority` of a `DSAuth`-ed contract. Returns: The address of the current `authority`. """ return Address(self._contract.functions.authority().call()) def set_authority(self, address: Address) -> Transact: """Set the `authority` of a `DSAuth`-ed contract. Args: address: The address of the new `authority`. Returns: A :py:class:`pymaker.Transact` instance, which can be used to trigger the transaction. """ assert (isinstance(address, Address)) return Transact(self, self.web3, self.abi, self.address, self._contract, 'setAuthority', [address.address]) def __repr__(self): return f"DSVault('{self.address}')"
class DSGuard(Contract): """A client for the `DSGuard` contract. You can find the source code of the `DSGuard` contract here: <https://github.com/dapphub/ds-guard>. Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `DSGuard` contract. """ abi = Contract._load_abi(__name__, 'abi/DSGuard.abi') bin = Contract._load_bin(__name__, 'abi/DSGuard.bin') ANY = int_to_bytes32(2**256 - 1) def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) @staticmethod def deploy(web3: Web3): return DSGuard(web3=web3, address=Contract._deploy(web3, DSGuard.abi, DSGuard.bin, [])) def permit(self, src, dst, sig: bytes) -> Transact: """Grant access to a function call. Args: src: Address of the caller, or `ANY`. dst: Address of the called contract, or `ANY`. sig: Signature of the called function, or `ANY`. Returns: A :py:class:`pymaker.Transact` instance, which can be used to trigger the transaction. """ assert (isinstance(src, Address) or isinstance(src, bytes)) assert (isinstance(dst, Address) or isinstance(dst, bytes)) assert (isinstance(sig, bytes) and len(sig) in (4, 32)) if isinstance(src, Address) and isinstance(dst, Address): method = 'permit(address,address,bytes32)' src = src.address dst = dst.address else: method = 'permit(bytes32,bytes32,bytes32)' return Transact(self, self.web3, self.abi, self.address, self._contract, method, [src, dst, sig]) def __repr__(self): return f"DSGuard('{self.address}')"
class Top(Contract): """A client for the `Top` contract. Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `Top` contract. """ abi = Contract._load_abi(__name__, 'abi/SaiTop.abi') bin = Contract._load_bin(__name__, 'abi/SaiTop.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) @staticmethod def deploy(web3: Web3, tub: Address, tap: Address): assert (isinstance(tub, Address)) assert (isinstance(tap, Address)) return Top(web3=web3, address=Contract._deploy(web3, Top.abi, Top.bin, [tub.address, tap.address])) def set_authority(self, address: Address) -> Transact: assert (isinstance(address, Address)) return Transact(self, self.web3, self.abi, self.address, self._contract, 'setAuthority', [address.address]) def fix(self) -> Ray: """Get the GEM per SAI settlement price. Returns: The GEM per SAI settlement (kill) price. """ return Ray(self._contract.functions.fix().call()) def cage(self) -> Transact: """Force settlement of the system at a current price. Returns: A :py:class:`pymaker.Transact` instance, which can be used to trigger the transaction. """ return Transact(self, self.web3, self.abi, self.address, self._contract, 'cage', []) # TODO vent def __eq__(self, other): assert (isinstance(other, Top)) return self.address == other.address def __repr__(self): return f"Top('{self.address}')"
class Vox(Contract): """A client for the `Vox` contract. Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `Vox` contract. """ abi = Contract._load_abi(__name__, 'abi/SaiVox.abi') bin = Contract._load_bin(__name__, 'abi/SaiVox.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) @staticmethod def deploy(web3: Web3, per: Ray): assert (isinstance(per, Ray)) return Vox(web3=web3, address=Contract._deploy(web3, Vox.abi, Vox.bin, [per.value])) def set_authority(self, address: Address) -> Transact: assert (isinstance(address, Address)) return Transact(self, self.web3, self.abi, self.address, self._contract, 'setAuthority', [address.address]) def era(self) -> int: """Return the current `Vox` timestamp. Returns: Timestamp as a unix timestamp. """ return self._contract.functions.era().call() def par(self) -> Ray: """Get the accrued holder fee (REF per SAI). Every invocation of this method calls `prod()` internally, so the value you receive is always up-to-date. But as calling it doesn't result in an Ethereum transaction, the actual `_par` value in the smart contract storage does not get updated. Returns: The accrued holder fee. """ return Ray(self._contract.functions.par().call()) def __eq__(self, other): assert (isinstance(other, Vox)) return self.address == other.address def __repr__(self): return f"Vox('{self.address}')"
def setup_method(self): self.web3 = Web3(HTTPProvider("http://localhost:8555")) self.web3.eth.defaultAccount = self.web3.eth.accounts[0] self.keeper_address = Address(self.web3.eth.defaultAccount) self.gal_address = Address(self.web3.eth.accounts[1]) self.other_address = Address(self.web3.eth.accounts[2]) # GemMock version of DSToken with push(bytes32, uint function) an hope(address) gem_abi = Contract._load_abi(__name__, '../lib/pymaker/tests/abi/GemMock.abi') gem_bin = Contract._load_bin(__name__, '../lib/pymaker/tests/abi/GemMock.bin') self.gem_addr = Contract._deploy(self.web3, gem_abi, gem_bin, [b'ABC']) self.gem = DSToken(web3=self.web3, address=self.gem_addr) self.dai_addr = Contract._deploy(self.web3, gem_abi, gem_bin, [b'DAI']) self.dai = DSToken(web3=self.web3, address=self.dai_addr) self.flipper = Flipper.deploy(self.web3, self.dai.address, self.gem.address) # Set allowance to allow flipper to move dai and gem self.dai.approve(self.flipper.address).transact() self.dai.approve( self.flipper.address).transact(from_address=self.gal_address) self.dai.approve( self.flipper.address).transact(from_address=self.other_address) self.gem.approve( self.flipper.address).transact(from_address=self.gal_address) self.gem.approve( self.flipper.address).transact(from_address=self.other_address) self.keeper = AuctionKeeper(args=args( f"--eth-from {self.keeper_address} " f"--flipper {self.flipper.address} " f"--model ./bogus-model.sh"), web3=self.web3) self.keeper.approve() # So that `keeper_address` and `other_address` can bid in auctions, # they both need to have DAI in their accounts. self.dai.mint(Wad.from_number(20000000)).transact() self.dai.transfer(self.other_address, Wad.from_number(10000000)).transact() # So that `gal_address` can kick auction he need to have GEM in his accounts self.gem.mint(Wad.from_number(1000000)).transact() self.gem.transfer(self.gal_address, Wad.from_number(1000000)).transact() self.model = MagicMock() self.model.get_stance = MagicMock(return_value=None) self.model_factory = self.keeper.auctions.model_factory self.model_factory.create_model = MagicMock(return_value=self.model)
class TEthfinexToken(ERC20Token): """A client for the `Trustless Ethfinex token wrappers. Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `TEthfinexToken` wrapper. """ abi = Contract._load_abi(__name__, 'abi/TETHFINEX.abi') bin = Contract._load_bin(__name__, 'abi/TETHFINEX.bin') abi_locker = Contract._load_abi(__name__, 'abi/LOCKER.abi') bin_locker = Contract._load_bin(__name__, 'abi/LOCKER.bin') def __init__(self, web3, address, token: str): assert (isinstance(token, str)) self.token = token super().__init__(web3, address) self._contract = self._get_contract(web3, self.abi, address) def deposit(self, amount: Wad, duration: int = 500) -> Transact: """Locks `amount` of token in to `TEthfinexToken`. Args: amount: Amount of token to be locked to `TEthfinexToken`. duration: Period of time (in hours) for locking the amount Returns: A :py:class:`pymaker.Transact` instance, which can be used to trigger the transaction. """ assert (isinstance(amount, Wad)) assert (isinstance(duration, int)) if self.token == "ETH": return Transact(self, self.web3, self.abi_locker, self.address, self._contract, 'deposit', [amount.value, duration], {'value': amount.value}) else: return Transact(self, self.web3, self.abi_locker, self.address, self._contract, 'deposit', [amount.value, duration], {}) def __repr__(self): return f"TEthfinexToken('{self.address}')"
class ShutdownModule(Contract): """A client for the `ESM` contract, which allows users to call `end.cage()` and thereby trigger a shutdown. Ref. <https://github.com/makerdao/esm/blob/master/src/ESM.sol> Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `ESM` contract.""" abi = Contract._load_abi(__name__, 'abi/ESM.abi') bin = Contract._load_bin(__name__, 'abi/ESM.bin') def __init__(self, web3: Web3, address: Address): assert isinstance(web3, Web3) assert isinstance(address, Address) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) def sum(self) -> Wad: """Total balance of MKR `join`ed to this contract""" return Wad(self._contract.functions.Sum().call()) def sum_of(self, address: Address) -> Wad: """MKR `join`ed to this contract by a specific account""" assert isinstance(address, Address) return Wad(self._contract.functions.sum(address.address).call()) def min(self) -> Wad: """Minimum amount of MKR required to call `fire`""" return Wad(self._contract.functions.min().call()) def join(self, value: Wad) -> Transact: """Before `fire` can be called, sufficient MKR must be `join`ed to this contract""" assert isinstance(value, Wad) return Transact(self, self.web3, self.abi, self.address, self._contract, 'join', [value.value]) def fire(self): """Calls `cage` on the `end` contract, initiating a shutdown.""" logger.info("Calling fire to cage the end") return Transact(self, self.web3, self.abi, self.address, self._contract, 'fire', []) def deny(self, address: Address): """Removes the Pause proxy's privileges from address""" return Transact(self, self.web3, self.abi, self.address, self._contract, 'deny', [address.address]) def burn(self): logger.info("Calling burn to burn all the joined MKR") return Transact(self, self.web3, self.abi, self.address, self._contract, 'burn', [])
def setup_method(self): GeneralMarketTest.setup_method(self) support_abi = Contract._load_abi(__name__, '../pymaker/abi/MakerOtcSupportMethods.abi') support_bin = Contract._load_bin(__name__, '../pymaker/abi/MakerOtcSupportMethods.bin') support_address = Contract._deploy(self.web3, support_abi, support_bin, []) self.price_oracle = OasisMockPriceOracle.deploy(self.web3) self.otc = MatchingMarket.deploy(self.web3, self.token1.address, Wad(0), self.price_oracle.address, support_address) self.otc.add_token_pair_whitelist(self.token1.address, self.token2.address).transact() self.otc.add_token_pair_whitelist(self.token1.address, self.token3.address).transact() self.otc.add_token_pair_whitelist(self.token2.address, self.token3.address).transact()
class Pot(Contract): """A client for the `Pot` contract, which implements the DSR. Ref. <https://github.com/makerdao/dss/blob/master/src/pot.sol> """ abi = Contract._load_abi(__name__, 'abi/Pot.abi') bin = Contract._load_bin(__name__, 'abi/Pot.bin') def __init__(self, web3: Web3, address: Address): assert isinstance(web3, Web3) assert isinstance(address, Address) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) def approve(self, source: Address, approval_function, **kwargs): """Approve the pot to access Dai from our Urns""" assert isinstance(source, Address) assert (callable(approval_function)) approval_function(ERC20Token(web3=self.web3, address=source), self.address, self.__class__.__name__, **kwargs) def pie_of(self, address: Address) -> Wad: assert isinstance(address, Address) return Wad(self._contract.functions.pie(address.address).call()) def pie(self) -> Wad: pie = self._contract.functions.Pie().call() return Wad(pie) def dsr(self) -> Ray: dsr = self._contract.functions.dsr().call() return Ray(dsr) def chi(self) -> Ray: chi = self._contract.functions.chi().call() return Ray(chi) def rho(self) -> datetime: rho = self._contract.functions.rho().call() return datetime.fromtimestamp(rho) def drip(self) -> Transact: return Transact(self, self.web3, self.abi, self.address, self._contract, 'drip', []) """ Join/Exit in Pot can be invoked through pymaker/dsrmanager.py and pymaker/dsr.py """ def __repr__(self): return f"Pot('{self.address}')"
class Jug(Contract): """A client for the `Jug` contract, which manages stability fees. Ref. <https://github.com/makerdao/dss/blob/master/src/jug.sol> """ abi = Contract._load_abi(__name__, 'abi/Jug.abi') bin = Contract._load_bin(__name__, 'abi/Jug.bin') def __init__(self, web3: Web3, address: Address): assert isinstance(web3, Web3) assert isinstance(address, Address) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) self.vat = Vat(web3, Address(self._contract.functions.vat().call())) self.vow = Vow(web3, Address(self._contract.functions.vow().call())) def init(self, ilk: Ilk) -> Transact: assert isinstance(ilk, Ilk) return Transact(self, self.web3, self.abi, self.address, self._contract, 'init', [ilk.toBytes()]) def wards(self, address: Address): assert isinstance(address, Address) return bool(self._contract.functions.wards(address.address).call()) def drip(self, ilk: Ilk) -> Transact: assert isinstance(ilk, Ilk) return Transact(self, self.web3, self.abi, self.address, self._contract, 'drip', [ilk.toBytes()]) def base(self) -> Ray: return Ray(self._contract.functions.base().call()) def duty(self, ilk: Ilk) -> Ray: assert isinstance(ilk, Ilk) return Ray(self._contract.functions.ilks(ilk.toBytes()).call()[0]) def rho(self, ilk: Ilk) -> int: assert isinstance(ilk, Ilk) return Web3.toInt( self._contract.functions.ilks(ilk.toBytes()).call()[1]) def __repr__(self): return f"Jug('{self.address}')"
class Spotter(Contract): """A client for the `Spotter` contract, which interacts with Vat for the purpose of managing collateral prices. Users generally have no need to interact with this contract; it is included for unit testing purposes. Ref. <https://github.com/makerdao/dss-deploy/blob/master/src/poke.sol> """ abi = Contract._load_abi(__name__, 'abi/Spotter.abi') bin = Contract._load_bin(__name__, 'abi/Spotter.bin') def __init__(self, web3: Web3, address: Address): assert isinstance(web3, Web3) assert isinstance(address, Address) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) def file_pip(self, ilk: Ilk, pip: Address) -> Transact: assert isinstance(ilk, Ilk) assert isinstance(pip, Address) return Transact(self, self.web3, self.abi, self.address, self._contract, 'file(bytes32,address)', [ilk.toBytes(), pip.address]) def file_par(self, par: Ray) -> Transact: assert isinstance(par, Ray) return Transact(self, self.web3, self.abi, self.address, self._contract, 'file(bytes32,uint256)', [Web3.toBytes(text="par"), par.value]) def file_mat(self, ilk: Ilk, mat: Ray) -> Transact: assert isinstance(ilk, Ilk) assert isinstance(mat, Ray) return Transact(self, self.web3, self.abi, self.address, self._contract, 'file(bytes32,bytes32,uint256)', [ilk.toBytes(), Web3.toBytes(text="mat"), mat.value]) def poke(self, ilk: Ilk) -> Transact: assert isinstance(ilk, Ilk) return Transact(self, self.web3, self.abi, self.address, self._contract, 'poke', [ilk.toBytes()]) def vat(self) -> Address: return Address(self._contract.call().vat()) def par(self) -> Ray: return Ray(self._contract.call().par()) def __repr__(self): return f"Spotter('{self.address}')"
class GemJoin5(GemJoin): """A client for the `GemJoin5` contract, which allows the user to deposit collateral into a new or existing vault. Ref. <https://github.com/makerdao/dss-deploy/blob/master/src/join.sol#L274> """ abi = Contract._load_abi(__name__, 'abi/GemJoin5.abi') bin = Contract._load_bin(__name__, 'abi/GemJoin5.bin') def __init__(self, web3: Web3, address: Address): super(GemJoin5, self).__init__(web3, address) self._token = self.gem() def dec(self) -> int: return int(self._contract.functions.dec().call())
class GemMock(Contract): """A client for `GemMock` contract. """ abi = Contract._load_abi(__name__, 'abi/GemMock.abi') bin = Contract._load_bin(__name__, 'abi/GemMock.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) @staticmethod def deploy(web3: Web3, vat: Address, ilk: Ilk, gem: Address): assert isinstance(web3, Web3) assert isinstance(vat, Address) assert isinstance(ilk, Ilk) assert isinstance(gem, Address) return GemMock( web3=web3, address=Contract._deploy( web3, GemMock.abi, GemMock.bin, [vat.address, ilk.toBytes(), gem.address])) def ilk(self): return Ilk.fromBytes(self._contract.functions.ilk().call()) def join(self, urn: Urn, value: Wad) -> Transact: assert (isinstance(urn, Urn)) assert (isinstance(value, Wad)) return Transact(self, self.web3, self.abi, self.address, self._contract, 'join', [urn.toBytes(), value.value]) def hope(self, guy: Address) -> Transact: assert (isinstance(guy, Address)) return Transact(self, self.web3, self.abi, self.address, self._contract, 'hope', [guy.address]) def __eq__(self, other): return self.address == other.address def __repr__(self): return f"GemMock('{self.address}')"
class Spotter(Contract): """A client for the `Spotter` contract. Ref. <https://github.com/makerdao/dss-deploy/blob/master/src/poke.sol> """ abi = Contract._load_abi(__name__, 'abi/Spotter.abi') bin = Contract._load_bin(__name__, 'abi/Spotter.bin') def __init__(self, web3: Web3, address: Address): assert isinstance(web3, Web3) assert isinstance(address, Address) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) @staticmethod def deploy(web3: Web3, pit: Address, ilk: Ilk): assert isinstance(web3, Web3) assert isinstance(pit, Address) assert isinstance(ilk, Ilk) return Spotter( web3=web3, address=Contract._deploy(web3, Spotter.abi, Spotter.bin, [pit.address, ilk.toBytes()])) def file_pip(self, pip: Address) -> Transact: assert isinstance(pip, Address) return Transact(self, self.web3, self.abi, self.address, self._contract, 'file(address)', [pip.address]) def file_mat(self, mat: Ray) -> Transact: assert isinstance(mat, Ray) return Transact(self, self.web3, self.abi, self.address, self._contract, 'file(uint256)', [mat.value]) def mat(self) -> Ray: return Ray(self._contract.call().mat()) def poke(self) -> Transact: return Transact(self, self.web3, self.abi, self.address, self._contract, 'poke', []) def __repr__(self): return f"Spotter('{self.address}')"
class DSProxyCache(Contract): """A client for the `DSProxyCache` contract. Ref. <https://github.com/dapphub/ds-proxy/blob/master/src/proxy.sol#L120> """ abi = Contract._load_abi(__name__, 'abi/DSProxyCache.abi') bin = Contract._load_bin(__name__, 'abi/DSProxyCache.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) @classmethod def deploy(cls, web3: Web3): return cls(web3=web3, address=Contract._deploy(web3, cls.abi, cls.bin, [])) def read(self, code: str) -> Optional[Address]: assert (isinstance(code, str)) if code.startswith('0x'): b32_code = hexstring_to_bytes(code) else: b32_code = hexstring_to_bytes('0x' + code) address = Address(self._contract.functions.read(b32_code).call()) if address == Address('0x0000000000000000000000000000000000000000'): return None else: return address def write(self, code: str): assert (isinstance(code, str)) if code.startswith('0x'): b32_code = hexstring_to_bytes(code) else: b32_code = hexstring_to_bytes('0x' + code) return Transact(self, self.web3, self.abi, self.address, self._contract, 'write', [b32_code]) def __repr__(self): return f"DSProxyCache('{self.address}')"
class DSRoles(Contract): """A client for the `DSRoles` contract, which manages lists of user roles and capabilities. You can find the source code of the `DSRoles` contract here: <https://github.com/dapphub/ds-roles>. Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `DSRoles` contract. """ abi = Contract._load_abi(__name__, 'abi/DSRoles.abi') bin = Contract._load_bin(__name__, 'abi/DSRoles.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) def is_root_user(self, who: Address) -> bool: assert isinstance(who, Address) return bool(self._contract.functions.isUserRoot(who.address).call()) def set_root_user(self, who: Address, enabled=True) -> Transact: assert isinstance(who, Address) return Transact(self, self.web3, self.abi, self.address, self._contract, "setRootUser", [who.address, enabled]) def has_user_role(self, who: Address, role: int) -> bool: assert isinstance(who, Address) assert isinstance(role, int) assert 0 <= role <= int('0xFFFFFFFF') return bool( self._contract.functions.hasUserRole(who.address, role).call()) def set_user_role(self, who: Address, role: int, enabled=True) -> Transact: assert isinstance(who, Address) assert isinstance(role, int) assert 0 <= role <= int('0xFFFFFFFF') return Transact(self, self.web3, self.abi, self.address, self._contract, "setUserRole", [who.address, role, enabled])
class DssProxyActionsDsr(Contract): """A client for the `DssProxyActionsDsr` contract. Ref. <https://github.com/makerdao/dss-proxy-actions/blob/master/src/DssProxyActions.sol> """ abi = Contract._load_abi(__name__, 'abi/DssProxyActionsDsr.abi') bin = Contract._load_bin(__name__, 'abi/DssProxyActionsDsr.bin') def __init__(self, web3: Web3, address: Address): assert isinstance(web3, Web3) assert isinstance(address, Address) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address)
class DaiJoin(Join): """A client for the `DaiJoin` contract, which allows the CDP holder to draw Dai from their Urn and repay it. Ref. <https://github.com/makerdao/dss/blob/master/src/join.sol> """ abi = Contract._load_abi(__name__, 'abi/DaiJoin.abi') bin = Contract._load_bin(__name__, 'abi/DaiJoin.bin') def __init__(self, web3: Web3, address: Address): super(DaiJoin, self).__init__(web3, address) self._token = self.dai() def dai(self) -> DSToken: address = Address(self._contract.functions.dai().call()) return DSToken(self.web3, address)
class DSSSpell(Contract): """A client for the `DSSSpell` contract, which houses logic that makes changes to the Maker Protocol. You can find the source code of the `DSSSpell` contract here: Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `DSSSpell` contract. """ # This ABI and BIN was used from a modified McdIlkLineSpell.sol, located here: https://gist.github.com/godsflaw/3a6cfcdbe8cc08d5df8b03f1be0432df abi = Contract._load_abi(__name__, 'abi/DSSSpell.abi') bin = Contract._load_bin(__name__, 'abi/DSSSpell.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) def done(self) -> bool: return self._contract.call().done() def eta(self) -> datetime: try: timestamp = self._contract.call().eta() except ValueError: timestamp = 0 return datetime.utcfromtimestamp(timestamp) @staticmethod def deploy(web3: Web3, pauseAddress: Address, vatAddress: Address): return DSSSpell(web3=web3, address=Contract._deploy( web3, DSSSpell.abi, DSSSpell.bin, [pauseAddress.address, vatAddress.address])) def schedule(self): return Transact(self, self.web3, self.abi, self.address, self._contract, 'schedule', []) def cast(self): return Transact(self, self.web3, self.abi, self.address, self._contract, 'cast', [])
class DSSBadSpell(Contract): """A client for the `DSSBadSpell` contract, which houses logic that makes changes to the Maker Protocol. You can find the source code of the `DSSBadSpell` contract here: Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `DSSBadSpell` contract. """ abi = Contract._load_abi(__name__, 'abi/DSSBadSpell.abi') bin = Contract._load_bin(__name__, 'abi/DSSBadSpell.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) def done(self) -> bool: return self._contract.functions.done().call() def eta(self) -> datetime: try: timestamp = self._contract.functions.eta().call() except ValueError: timestamp = 0 return datetime.utcfromtimestamp(timestamp) @staticmethod def deploy(web3: Web3): return DSSBadSpell(web3=web3, address=Contract._deploy(web3, DSSBadSpell.abi, DSSBadSpell.bin, [])) def schedule(self): return Transact(self, self.web3, self.abi, self.address, self._contract, 'schedule', []) def cast(self): return Transact(self, self.web3, self.abi, self.address, self._contract, 'cast', [])
class TokenFaucet(Contract): """A client for the `TokenFaucet` contract, to obtain ERC-20 tokens on testnets for testing purposes. Ref. <https://github.com/makerdao/token-faucet/blob/master/src/TokenFaucet.sol> """ abi = Contract._load_abi(__name__, 'abi/TokenFaucet.abi') bin = Contract._load_bin(__name__, 'abi/TokenFaucet.bin') def __init__(self, web3: Web3, address: Address): assert isinstance(web3, Web3) assert isinstance(address, Address) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) def gulp(self, address: Address): return Transact(self, self.web3, self.abi, self.address, self._contract, 'gulp(address)', [address.address])
def setup_method(self): self.web3 = Web3(HTTPProvider("http://localhost:8555")) self.web3.eth.defaultAccount = self.web3.eth.accounts[0] self.our_address = Address(self.web3.eth.defaultAccount) self.token1 = DSToken.deploy(self.web3, 'AAA') self.token1_tokenclass = Token('AAA', self.token1.address, 18) self.token1.mint(Wad.from_number(10000)).transact() self.token2 = DSToken.deploy(self.web3, 'BBB') self.token2_tokenclass = Token('BBB', self.token2.address, 6) self.token2.mint(Wad.from_number(10000)).transact() support_abi = Contract._load_abi(__name__, '../pymaker/abi/MakerOtcSupportMethods.abi') support_bin = Contract._load_bin(__name__, '../pymaker/abi/MakerOtcSupportMethods.bin') support_address = Contract._deploy(self.web3, support_abi, support_bin, []) price_oracle = OasisMockPriceOracle.deploy(self.web3) self.otc = MatchingMarket.deploy(self.web3, self.token1.address, Wad(0), price_oracle.address, support_address) self.otc.add_token_pair_whitelist(self.token1.address, self.token2.address).transact() self.otc.approve([self.token1, self.token2], directly())
class GemJoin(Join): """A client for the `GemJoin` contract, which allows the user to deposit collateral into a new or existing CDP. Ref. <https://github.com/makerdao/dss/blob/master/src/join.sol> """ abi = Contract._load_abi(__name__, 'abi/GemJoin.abi') bin = Contract._load_bin(__name__, 'abi/GemJoin.bin') def __init__(self, web3: Web3, address: Address): super(GemJoin, self).__init__(web3, address) self._token = self.gem() def ilk(self): return Ilk.fromBytes(self._contract.call().ilk()) def gem(self) -> DSToken: address = Address(self._contract.call().gem()) return DSToken(self.web3, address)
class OSM(Contract): """A client for the `OSM` contract. You can find the source code of the `OSM` contract here: <https://github.com/makerdao/osm>. Attributes: web3: An instance of `Web` from `web3.py`. address: Ethereum address of the `OSM` contract. """ abi = Contract._load_abi(__name__, 'abi/OSM.abi') bin = Contract._load_bin(__name__, 'abi/OSM.bin') def __init__(self, web3: Web3, address: Address): assert (isinstance(web3, Web3)) assert (isinstance(address, Address)) self.web3 = web3 self.address = address self._contract = self._get_contract(web3, self.abi, address) def poke(self) -> Transact: return Transact(self, self.web3, self.abi, self.address, self._contract, 'poke', []) def peek(self) -> Wad: return Wad(self._extract_price(3)) def peep(self) -> Wad: return Wad(self._extract_price(4)) def zzz(self) -> int: return self._contract.functions.zzz().call() def _extract_price(self, storage_slot: int) -> int: assert isinstance(storage_slot, int) return Web3.toInt( self.web3.eth.getStorageAt(self.address.address, storage_slot)[16:]) def __repr__(self): return f"OSM('{self.address}')"