Skip to content

Commit

Permalink
made added immutable addrs public, improved test related naming
Browse files Browse the repository at this point in the history
  • Loading branch information
d10r committed Sep 23, 2023
1 parent 2422b18 commit 9e801ec
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 10 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ Hands upgradability permission to a hardcoded account `UPGRADE_ADMIN`.
Fork testing using FRACTION on Optimism:

```
yarn test:foundry:fraction-on-op
ADMIN_ADDR=0x388e96dfe68b30892af93f30f5035602d8d51487 yarn test:fork:fraction-on-op
```

Deploy (to Optimism Goerli, using the deployer account as UPGRADE_ADMIN):
Expand Down
4 changes: 2 additions & 2 deletions contracts/alternative-logic/BridgedSuperToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ interface IMintBurn {
*/
contract BridgedSuperToken is SuperToken, IMintBurn {
// the account with upgrade permission. In order to change, upgrade to a logic with different value.
address immutable UPGRADE_ADMIN;
address public immutable UPGRADE_ADMIN;

// the account with mint/burn permission. In order to change, upgrade to a logic with different value.
address immutable BRIDGE_ADDR;
address public immutable BRIDGE_ADDR;

error NO_PERMISSION();

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"scripts": {
"build": "truffle compile --all",
"test": "truffle test",
"test:foundry": "scripts/test-foundry.sh",
"test:foundry:fraction-on-op": "TOKEN=0xbd80cfa9d93a87d1bb895f810ea348e496611cd4 scripts/test-foundry.sh optimism-mainnet",
"test:fork": "scripts/run-test-foundry.sh",
"test:fork:fraction-on-op": "TOKEN=0xbd80cfa9d93a87d1bb895f810ea348e496611cd4 scripts/run-fork-test.sh optimism-mainnet BridgedSuperTokenForkTest",
"prepare": "husky install"
},
"dependencies": {
Expand Down
12 changes: 7 additions & 5 deletions scripts/test-foundry.sh → scripts/run-fork-test.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
#!/bin/bash

# usage: test.sh <network>
# usage: run-fork-test.sh <network> <testContract> [<extraArg> ...]

set -eu

network=$1
testContract=$2
shift 2
extraArgs=$@

metadata=$(curl -s "https://raw.githubusercontent.com/superfluid-finance/protocol-monorepo/dev/packages/metadata/networks.json")

# takes the network name as argument
function test_network() {
network=$1

rpc=${RPC:-"https://${network}.rpc.x.superfluid.dev"}

echo "=============== Testing $network... ==================="
Expand All @@ -23,7 +24,8 @@ function test_network() {
# Print the host address
echo "Host: $host"

RPC=$rpc HOST_ADDR=$host forge test -vvv
set -x
RPC=$rpc HOST_ADDR=$host forge test --match-contract $testContract $extraArgs
}

test_network $network
test_network
File renamed without changes.
141 changes: 141 additions & 0 deletions test/foundry/BridgedSuperToken.fork.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.19;

import "forge-std/Test.sol";
// TODO: fix this path
import { IMintBurn, BridgedSuperToken } from "../../contracts/alternative-logic/BridgedSuperToken.sol";
import {
ISuperfluid,
ISuperfluidGovernance,
ISuperToken,
ISuperfluidToken
} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol";
import { IConstantOutflowNFT } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/IConstantOutflowNFT.sol";
import { IConstantInflowNFT } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/IConstantInflowNFT.sol";
import { UUPSProxiable } from "@superfluid-finance/ethereum-contracts/contracts/upgradability/UUPSProxiable.sol";
import { CFAv1Forwarder } from "@superfluid-finance/ethereum-contracts/contracts/utils/CFAv1Forwarder.sol";

contract BridgedSuperTokenForkTest is Test {

address HOST_ADDR = vm.envAddress("HOST_ADDR");
address ADMIN_ADDR = vm.envAddress("ADMIN_ADDR"); // token admin (overrides host)
ISuperfluid host = ISuperfluid(HOST_ADDR);
address GOV_ADDR;
ISuperfluidGovernance gov;
address TOKEN = vm.envAddress("TOKEN");
ISuperToken token = ISuperToken(TOKEN);
CFAv1Forwarder cfaFwd = CFAv1Forwarder(0xcfA132E353cB4E398080B9700609bb008eceB125);
address constant upgradeAdmin = address(0x420);
address constant bridgeAddr = address(0x421);
address constant alice = address(0x690);
address constant bob = address(0x691);

constructor() {
string memory rpc = vm.envString("RPC");
vm.createSelectFork(rpc);
console.log("token symbol: %s", token.symbol());

GOV_ADDR = address(host.getGovernance());
gov = ISuperfluidGovernance(host.getGovernance());
ADMIN_ADDR = ADMIN_ADDR == address(0) ? HOST_ADDR : ADMIN_ADDR;
}

// HELPERS

function deployNewLogic() public returns(address) {
IConstantOutflowNFT cof = token.CONSTANT_OUTFLOW_NFT();
IConstantInflowNFT cif = token.CONSTANT_INFLOW_NFT();
BridgedSuperToken newLogic = new BridgedSuperToken(
ISuperfluid(HOST_ADDR),
cof,
cif,
upgradeAdmin,
bridgeAddr
);
console.log("new logic deployed to %s", address(newLogic));
return address(newLogic);
}

function smokeTestSuperToken(address superTokenAddr) public {
ISuperToken superToken = ISuperToken(superTokenAddr);

vm.startPrank(alice);
deal(address(superTokenAddr), alice, uint256(100e18));

uint256 initBal = superToken.balanceOf(address(this));

// start a stream using the forwarder
cfaFwd.setFlowrate(superToken, address(this), 1e9);
skip(1000);
assertEq(superToken.balanceOf(address(this)), initBal + 1e9 * 1000);

// stop the stream
cfaFwd.setFlowrate(superToken, address(this), 0);
skip(1000);
assertEq(superToken.balanceOf(address(this)), initBal + 1e9 * 1000); // no change

vm.stopPrank();
}

// TESTS

function testUpgrade() public {
address newLogic = deployNewLogic();

vm.startPrank(ADMIN_ADDR);
UUPSProxiable(address(token)).updateCode(newLogic);
vm.stopPrank();

smokeTestSuperToken(TOKEN);

address newLogic2 = deployNewLogic();
vm.startPrank(HOST_ADDR);
// the token is now self-sovereign
vm.expectRevert(BridgedSuperToken.NO_PERMISSION.selector);
UUPSProxiable(address(token)).updateCode(newLogic2);
vm.stopPrank();

vm.startPrank(upgradeAdmin);
UUPSProxiable(address(token)).updateCode(newLogic2);
vm.stopPrank();

smokeTestSuperToken(TOKEN);
}

function testMintBurn() public {
// upgrade
address newLogic = deployNewLogic();
vm.startPrank(ADMIN_ADDR);
UUPSProxiable(address(token)).updateCode(newLogic);
vm.stopPrank();

// only the bridge can mint/burn
vm.startPrank(alice);
vm.expectRevert(BridgedSuperToken.NO_PERMISSION.selector);
IMintBurn(TOKEN).mint(bob, 42e18);
vm.expectRevert(BridgedSuperToken.NO_PERMISSION.selector);
IMintBurn(TOKEN).burn(bob, 42e18);
vm.stopPrank();

// the bridge giveth
vm.startPrank(bridgeAddr);
IMintBurn(TOKEN).mint(bob, 42e18);
assertEq(token.balanceOf(bob), 42e18);

vm.startPrank(bridgeAddr);
IMintBurn(TOKEN).mint(bob, 2e18);
assertEq(token.balanceOf(bob), 44e18);

// ... and the bridge taketh away
IMintBurn(TOKEN).burn(bob, 43e18);
assertEq(token.balanceOf(bob), 1e18);

IMintBurn(TOKEN).burn(bob, 1e18);
assertEq(token.balanceOf(bob), 0);

// but nomore than there is to take
vm.expectRevert(ISuperfluidToken.SF_TOKEN_BURN_INSUFFICIENT_BALANCE.selector);
IMintBurn(TOKEN).burn(bob, 1e18);
vm.stopPrank();
}
}

0 comments on commit 9e801ec

Please sign in to comment.