diff --git a/contracts/utils/MakerOracle.vy b/contracts/utils/MakerOracle.vy new file mode 100644 index 00000000..bd4a9a7a --- /dev/null +++ b/contracts/utils/MakerOracle.vy @@ -0,0 +1,45 @@ +# @version 0.2.7 + +interface OSM: + def bud(user: address) -> (bool): view + def peek() -> (uint256, bool): view + def peep() -> (uint256, bool): view + + +owner: public(address) +users: public(HashMap[address, bool]) +oracle: public(OSM) + + +@external +def __init__(src: address): + self.owner = msg.sender + self.oracle = OSM(src) + + +@external +def set_owner(new_owner: address): + assert msg.sender == self.owner + self.owner = new_owner + + +@external +def set_user(user: address, allowed: bool): + assert msg.sender == self.owner + self.users[user] = allowed + + +@view +@external +def peek() -> (uint256, bool): + assert self.users[msg.sender], "not user" + assert self.oracle.bud(self), "not bud" + return self.oracle.peek() + + +@view +@external +def peep() -> (uint256, bool): + assert self.users[msg.sender], "not user" + assert self.oracle.bud(self), "not bud" + return self.oracle.peep() diff --git a/interfaces/maker/OracleSecurityModule.sol b/interfaces/maker/OracleSecurityModule.sol index e8b6c2cc..184bd49a 100644 --- a/interfaces/maker/OracleSecurityModule.sol +++ b/interfaces/maker/OracleSecurityModule.sol @@ -6,4 +6,6 @@ interface OracleSecurityModule { function peep() external view returns (bytes32, bool); function bud(address) external view returns (uint256); + + function kiss(address a) external; } diff --git a/tests/functional/utils/test_maker_oracle.py b/tests/functional/utils/test_maker_oracle.py new file mode 100644 index 00000000..f0131059 --- /dev/null +++ b/tests/functional/utils/test_maker_oracle.py @@ -0,0 +1,39 @@ +import pytest +import brownie + +oracles = { + "BTC/USD": "0xf185d0682d50819263941e5f4EacC763CC5C6C42", + "ETH/USD": "0x81FE72B5A8d1A857d176C3E7d5Bd2679A9B85763", + "YFI/USD": "0x5F122465bCf86F45922036970Be6DD7F58820214", +} + + +@pytest.mark.parametrize("name", oracles) +def test_maker_oracle(MakerOracle, accounts, interface, name): + osm_mom = accounts.at("0x76416A4d5190d071bfed309861527431304aA14f", force=True) + source = interface.OracleSecurityModule(oracles[name]) + deployer, reader = accounts[:2] + oracle = MakerOracle.deploy(source, {"from": deployer}) + oracle.set_user(reader, True) + assert oracle.users(reader) + for func in [oracle.peek, oracle.peep]: + with brownie.reverts("not user"): + func() + with brownie.reverts("not bud"): + func({"from": reader}) + source.kiss(oracle, {"from": osm_mom}) + for func in [oracle.peek, oracle.peep]: + val, has = func({"from": reader}) + print(val.to("ether"), has) + assert val > 0 + assert has + + +def test_maker_oracle_auth(MakerOracle, accounts): + deployer, owner, rando = accounts[:3] + oracle = MakerOracle.deploy(oracles["YFI/USD"], {"from": deployer}) + assert oracle.owner() == deployer + oracle.set_owner(owner) + assert oracle.owner() == owner + with brownie.reverts(): + oracle.set_owner(rando, {"from": rando})