Skip to content

Instantly share code, notes, and snippets.

@Falilah
Created March 4, 2024 06:00

The first file is a foundry test that run on a state for setting paycrest admin functionalities, which allow users to create order and in turn allow aggregator to settle part payment in order to validate the POC of the bug in question the second file is a full stack traces of all the transactions involved in the test file.

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Test, console2} from "forge-std/Test.sol";
import {Paycrest} from "../../contracts/Paycrest.sol";
import {PaycrestSettingManager} from "../../contracts/PaycrestSettingManager.sol";
import {SharedStructs} from "../../contracts/libraries/SharedStructs.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {MockUSDT} from "../../contracts/mocks/MockUSDC.sol";
contract testPaycrest is Test{
Paycrest paycrest;
ERC1967Proxy proxy;
address owner = makeAddr("Owner");
address treasury = makeAddr("treasury");
address aggregator = makeAddr("aggregator");
MockUSDT Usdt;
function setUp() public{
vm.startPrank(owner);
paycrest = new Paycrest();
proxy = new ERC1967Proxy(address(paycrest), "");
paycrest = Paycrest(address(proxy));
paycrest.initialize();
vm.stopPrank();
Usdt = new MockUSDT();
}
function testOwnerLogic() public{
address own = paycrest.owner();
assertEq(own, owner);
vm.startPrank(owner);
paycrest.settingManagerBool("token", address(Usdt), true);
SharedStructs.Institution memory institution = SharedStructs.Institution("ABNGNGLA","ACCESS BANK");
SharedStructs.Institution memory institution2 = SharedStructs.Institution("DBLNNGLA","DIAMOND BANK");
SharedStructs.Institution[] memory institutions = new SharedStructs.Institution[](2);
institutions[0] = institution;
institutions[1] = institution2;
paycrest.setSupportedInstitutions("NGN", institutions);
paycrest.updateProtocolFees(2);
paycrest.updateProtocolAddresses("treasury", treasury);
paycrest.updateProtocolAddresses("aggregator", aggregator);
vm.stopPrank();
}
function testpartOrderSettle() external{
testOwnerLogic();
Usdt.approve(address(paycrest), 300_000e18);
address _senderFeeRecipient = makeAddr("_senderFeeRecipient");
address _refundAddress = makeAddr("_refundAddress");
address liquidityProvider = makeAddr("LiquidtyProvider");
string memory messageHash = "09090990901 ACCESS BANK Jeff Dean";
assertEq(Usdt.balanceOf(address(paycrest)), 0);
uint fullOrderAmount = 200_000e18;
bytes32 id = paycrest.createOrder(address(Usdt), fullOrderAmount, "ABNGNGLA", "to mother", 1_500, _senderFeeRecipient, 0, _refundAddress, messageHash);
//Aggregator settle 50% of the order
vm.startPrank(aggregator);
paycrest.settle("", id, "to mother", liquidityProvider, 50_000);
// assert balance left in paycrest is 0 usdt after settling 50% of the order leaving protocol fee and sender fee in the contract with no funds to settle other part of the order
//get the value of fee based on the percentage set
uint protocolfee = (fullOrderAmount * 2) / 100_000;
assertEq(Usdt.balanceOf(address(paycrest)), protocolfee);
// assert liquidty provider got the full amount of settling part payment of the order excluding the protocol fee.
// get protocol fee
assertEq(Usdt.balanceOf(liquidityProvider), (fullOrderAmount - protocolfee));
}
[2793610] testPaycrest::setUp()
├─ [0] VM::startPrank(Owner: [0x93B07479cC807d037A98B6bB122CE8201958a595])
│ └─ ← ()
├─ [1822380] → new Paycrest@0x6E1734aC57e76fcD7fD66266Ae0C2547dB3A713a
│ ├─ emit Initialized(version: 255)
│ └─ ← 9222 bytes of code
├─ [59670] → new ERC1967Proxy@0xb53e0264f951C0ee4cA20Cfd5a082B8251844BD5
│ ├─ emit Upgraded(implementation: Paycrest: [0x6E1734aC57e76fcD7fD66266Ae0C2547dB3A713a])
│ └─ ← 1345 bytes of code
├─ [73213] ERC1967Proxy::initialize()
│ ├─ [72821] Paycrest::initialize() [delegatecall]
│ │ ├─ emit OwnershipTransferred(previousOwner: 0x0000000000000000000000000000000000000000, newOwner: Owner: [0x93B07479cC807d037A98B6bB122CE8201958a595])
│ │ ├─ emit Initialized(version: 1)
│ │ └─ ← ()
│ └─ ← ()
├─ [0] VM::stopPrank()
│ └─ ← ()
├─ [667030] → new MockUSDT@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
│ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: testPaycrest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], value: 1000000000000000000000000 [1e24])
│ └─ ← 3654 bytes of code
└─ ← ()
[600920] testPaycrest::testpartOrderSettle()
├─ [7285] ERC1967Proxy::owner() [staticcall]
│ ├─ [2390] Paycrest::owner() [delegatecall]
│ │ └─ ← Owner: [0x93B07479cC807d037A98B6bB122CE8201958a595]
│ └─ ← Owner: [0x93B07479cC807d037A98B6bB122CE8201958a595]
├─ [0] VM::startPrank(Owner: [0x93B07479cC807d037A98B6bB122CE8201958a595])
│ └─ ← ()
├─ [24920] ERC1967Proxy::settingManagerBool(0x746f6b656e000000000000000000000000000000000000000000000000000000, MockUSDT: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f], true)
│ ├─ [24516] Paycrest::settingManagerBool(0x746f6b656e000000000000000000000000000000000000000000000000000000, MockUSDT: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f], true) [delegatecall]
│ │ ├─ emit SettingManagerBool(what: 0x746f6b656e000000000000000000000000000000000000000000000000000000, value: MockUSDT: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f], status: true)
│ │ └─ ← ()
│ └─ ← ()
├─ [202168] ERC1967Proxy::setSupportedInstitutions(0x4e474e0000000000000000000000000000000000000000000000000000000000, [Institution({ code: 0x41424e474e474c41000000000000000000000000000000000000000000000000, name: 0x4143434553532042414e4b000000000000000000000000000000000000000000 }), Institution({ code: 0x44424c4e4e474c41000000000000000000000000000000000000000000000000, name: 0x4449414d4f4e442042414e4b0000000000000000000000000000000000000000 })])
│ ├─ [201740] Paycrest::setSupportedInstitutions(0x4e474e0000000000000000000000000000000000000000000000000000000000, [Institution({ code: 0x41424e474e474c41000000000000000000000000000000000000000000000000, name: 0x4143434553532042414e4b000000000000000000000000000000000000000000 }), Institution({ code: 0x44424c4e4e474c41000000000000000000000000000000000000000000000000, name: 0x4449414d4f4e442042414e4b0000000000000000000000000000000000000000 })]) [delegatecall]
│ │ └─ ← ()
│ └─ ← ()
├─ [24151] ERC1967Proxy::updateProtocolFees(2)
│ ├─ [23756] Paycrest::updateProtocolFees(2) [delegatecall]
│ │ ├─ emit ProtocolFeesUpdated(protocolFee: 2)
│ │ └─ ← ()
│ └─ ← ()
├─ [2562] ERC1967Proxy::updateProtocolAddresses(0x7472656173757279000000000000000000000000000000000000000000000000, treasury: [0xf43Bca55E8091977223Fa5b776E23528D205dcA8])
│ ├─ [2164] Paycrest::updateProtocolAddresses(0x7472656173757279000000000000000000000000000000000000000000000000, treasury: [0xf43Bca55E8091977223Fa5b776E23528D205dcA8]) [delegatecall]
│ │ ├─ emit ProtocolAddressesUpdated(treasuryAddress: treasury: [0xf43Bca55E8091977223Fa5b776E23528D205dcA8])
│ │ └─ ← ()
│ └─ ← ()
├─ [24448] ERC1967Proxy::updateProtocolAddresses(0x61676772656761746f7200000000000000000000000000000000000000000000, aggregator: [0xf3335152C921451f9342fE6F96963632a9599240])
│ ├─ [24050] Paycrest::updateProtocolAddresses(0x61676772656761746f7200000000000000000000000000000000000000000000, aggregator: [0xf3335152C921451f9342fE6F96963632a9599240]) [delegatecall]
│ │ ├─ emit ProtocolAddressesUpdated(treasuryAddress: treasury: [0xf43Bca55E8091977223Fa5b776E23528D205dcA8])
│ │ └─ ← ()
│ └─ ← ()
├─ [0] VM::stopPrank()
│ └─ ← ()
├─ [24652] MockUSDT::approve(ERC1967Proxy: [0xb53e0264f951C0ee4cA20Cfd5a082B8251844BD5], 300000000000000000000000 [3e23])
│ ├─ emit Approval(owner: testPaycrest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], spender: ERC1967Proxy: [0xb53e0264f951C0ee4cA20Cfd5a082B8251844BD5], value: 300000000000000000000000 [3e23])
│ └─ ← true
├─ [0] VM::addr(<pk>) [staticcall]
│ └─ ← _senderFeeRecipient: [0xD14397cAc5EE9030Fac76E76Bc9A05473B66D2e5]
├─ [0] VM::label(_senderFeeRecipient: [0xD14397cAc5EE9030Fac76E76Bc9A05473B66D2e5], "_senderFeeRecipient")
│ └─ ← ()
├─ [0] VM::addr(<pk>) [staticcall]
│ └─ ← _refundAddress: [0xA8972839412485c15Eb0E94C441CEF7f061C572C]
├─ [0] VM::label(_refundAddress: [0xA8972839412485c15Eb0E94C441CEF7f061C572C], "_refundAddress")
│ └─ ← ()
├─ [0] VM::addr(<pk>) [staticcall]
│ └─ ← LiquidtyProvider: [0xFA6dC8C776eb2E83dF7Fe929f443856701EB1787]
├─ [0] VM::label(LiquidtyProvider: [0xFA6dC8C776eb2E83dF7Fe929f443856701EB1787], "LiquidtyProvider")
│ └─ ← ()
├─ [2563] MockUSDT::balanceOf(ERC1967Proxy: [0xb53e0264f951C0ee4cA20Cfd5a082B8251844BD5]) [staticcall]
│ └─ ← 0
├─ [223541] ERC1967Proxy::createOrder(MockUSDT: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f], 200000000000000000000000 [2e23], 0x41424e474e474c41000000000000000000000000000000000000000000000000, 0x746f206d6f746865720000000000000000000000000000000000000000000000, 1500, _senderFeeRecipient: [0xD14397cAc5EE9030Fac76E76Bc9A05473B66D2e5], 0, _refundAddress: [0xA8972839412485c15Eb0E94C441CEF7f061C572C], "09090990901 ACCESS BANK Jeff Dean")
│ ├─ [223080] Paycrest::createOrder(MockUSDT: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f], 200000000000000000000000 [2e23], 0x41424e474e474c41000000000000000000000000000000000000000000000000, 0x746f206d6f746865720000000000000000000000000000000000000000000000, 1500, _senderFeeRecipient: [0xD14397cAc5EE9030Fac76E76Bc9A05473B66D2e5], 0, _refundAddress: [0xA8972839412485c15Eb0E94C441CEF7f061C572C], "09090990901 ACCESS BANK Jeff Dean") [delegatecall]
│ │ ├─ [30479] MockUSDT::transferFrom(testPaycrest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], ERC1967Proxy: [0xb53e0264f951C0ee4cA20Cfd5a082B8251844BD5], 200000000000000000000000 [2e23])
│ │ │ ├─ emit Approval(owner: testPaycrest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], spender: ERC1967Proxy: [0xb53e0264f951C0ee4cA20Cfd5a082B8251844BD5], value: 100000000000000000000000 [1e23])
│ │ │ ├─ emit Transfer(from: testPaycrest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], to: ERC1967Proxy: [0xb53e0264f951C0ee4cA20Cfd5a082B8251844BD5], value: 200000000000000000000000 [2e23])
│ │ │ └─ ← true
│ │ ├─ emit OrderCreated(token: MockUSDT: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f], amount: 199996000000000000000000 [1.999e23], protocolFee: 4000000000000000000 [4e18], orderId: 0xb38645331535d8a24250bd866c230d0d85c11b90105fdba49ccc7bb4d9c6bc96, rate: 1500, institutionCode: 0x41424e474e474c41000000000000000000000000000000000000000000000000, label: 0x746f206d6f746865720000000000000000000000000000000000000000000000, messageHash: "09090990901 ACCESS BANK Jeff Dean")
│ │ └─ ← 0xb38645331535d8a24250bd866c230d0d85c11b90105fdba49ccc7bb4d9c6bc96
│ └─ ← 0xb38645331535d8a24250bd866c230d0d85c11b90105fdba49ccc7bb4d9c6bc96
├─ [0] VM::startPrank(aggregator: [0xf3335152C921451f9342fE6F96963632a9599240])
│ └─ ← ()
├─ [30610] ERC1967Proxy::settle(0x0000000000000000000000000000000000000000000000000000000000000000, 0xb38645331535d8a24250bd866c230d0d85c11b90105fdba49ccc7bb4d9c6bc96, 0x746f206d6f746865720000000000000000000000000000000000000000000000, LiquidtyProvider: [0xFA6dC8C776eb2E83dF7Fe929f443856701EB1787], 50000 [5e4])
│ ├─ [30188] Paycrest::settle(0x0000000000000000000000000000000000000000000000000000000000000000, 0xb38645331535d8a24250bd866c230d0d85c11b90105fdba49ccc7bb4d9c6bc96, 0x746f206d6f746865720000000000000000000000000000000000000000000000, LiquidtyProvider: [0xFA6dC8C776eb2E83dF7Fe929f443856701EB1787], 50000 [5e4]) [delegatecall]
│ │ ├─ [25016] MockUSDT::transfer(LiquidtyProvider: [0xFA6dC8C776eb2E83dF7Fe929f443856701EB1787], 199996000000000000000000 [1.999e23])
│ │ │ ├─ emit Transfer(from: ERC1967Proxy: [0xb53e0264f951C0ee4cA20Cfd5a082B8251844BD5], to: LiquidtyProvider: [0xFA6dC8C776eb2E83dF7Fe929f443856701EB1787], value: 199996000000000000000000 [1.999e23])
│ │ │ └─ ← true
│ │ ├─ emit OrderSettled(splitOrderId: 0x0000000000000000000000000000000000000000000000000000000000000000, orderId: 0xb38645331535d8a24250bd866c230d0d85c11b90105fdba49ccc7bb4d9c6bc96, label: 0x746f206d6f746865720000000000000000000000000000000000000000000000, liquidityProvider: LiquidtyProvider: [0xFA6dC8C776eb2E83dF7Fe929f443856701EB1787], settlePercent: 50000 [5e4])
│ │ └─ ← 0xb38645331535d8a24250bd866c230d0d85c11b90105fdba49ccc7bb4d9c6bc96, MockUSDT: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f]
│ └─ ← 0xb38645331535d8a24250bd866c230d0d85c11b90105fdba49ccc7bb4d9c6bc96, MockUSDT: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f]
├─ [563] MockUSDT::balanceOf(ERC1967Proxy: [0xb53e0264f951C0ee4cA20Cfd5a082B8251844BD5]) [staticcall]
│ └─ ← 4000000000000000000 [4e18]
├─ [563] MockUSDT::balanceOf(LiquidtyProvider: [0xFA6dC8C776eb2E83dF7Fe929f443856701EB1787]) [staticcall]
│ └─ ← 199996000000000000000000 [1.999e23]
└─ ← ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment