diff --git a/src/err/ErrFtso.sol b/src/err/ErrFtso.sol index 83b4c05..6e4c9a1 100644 --- a/src/err/ErrFtso.sol +++ b/src/err/ErrFtso.sol @@ -28,3 +28,6 @@ error InconsistentFtso(); /// Thrown when decimals are too large to handle safely. /// @param decimals The decimals that were too large. error DecimalsTooLarge(uint256 decimals); + +/// Thrown when the sFLR contract returns a zero exchange rate. +error ZeroSFLRRate(); diff --git a/src/generated/FlareFtsoWords.pointers.sol b/src/generated/FlareFtsoWords.pointers.sol index 28c9b43..6f6a67f 100644 --- a/src/generated/FlareFtsoWords.pointers.sol +++ b/src/generated/FlareFtsoWords.pointers.sol @@ -10,7 +10,7 @@ pragma solidity ^0.8.25; // file needs the contract to exist so that it can be compiled. /// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0x7ef751074fac00d4c9e13cf7df7d246255a6d0218f47696723309abc7dfda599); +bytes32 constant BYTECODE_HASH = bytes32(0x69ffc4160d6551b77f501f51e6e53d7825dcd7318519779f877261ebd37b7da0); /// @dev The hash of the meta that describes the contract. bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0x4ccb316fd35a2abbee0016f38926a4c95b6270b229c85a9acf8a3a52b36bfedc); diff --git a/src/lib/sflr/LibSceptreStakedFlare.sol b/src/lib/sflr/LibSceptreStakedFlare.sol index ed0ddbc..e971c95 100644 --- a/src/lib/sflr/LibSceptreStakedFlare.sol +++ b/src/lib/sflr/LibSceptreStakedFlare.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.19; import {IStakedFlr} from "../../interface/IStakedFlr.sol"; +import {ZeroSFLRRate} from "../../err/ErrFtso.sol"; /// @dev Immutable upgradeable proxy contract to the sFLR contract. IStakedFlr constant SFLR_CONTRACT = IStakedFlr(address(0x12e605bc104e93B45e1aD99F9e555f659051c2BB)); @@ -13,6 +14,8 @@ library LibSceptreStakedFlare { /// according to the sFLR contract's current exchange rate. //forge-lint: disable-next-line(mixed-case-function) function getSFLRPerFLR18() internal view returns (uint256) { - return SFLR_CONTRACT.getSharesByPooledFlr(1e18); + uint256 rate = SFLR_CONTRACT.getSharesByPooledFlr(1e18); + if (rate == 0) revert ZeroSFLRRate(); + return rate; } } diff --git a/test/src/lib/sflr/LibSceptreStakedFlare.t.sol b/test/src/lib/sflr/LibSceptreStakedFlare.t.sol index cf91014..9a415f7 100644 --- a/test/src/lib/sflr/LibSceptreStakedFlare.t.sol +++ b/test/src/lib/sflr/LibSceptreStakedFlare.t.sol @@ -4,7 +4,9 @@ pragma solidity =0.8.25; import {Test} from "forge-std-1.16.1/src/Test.sol"; import {LibFork} from "test/fork/LibFork.sol"; -import {LibSceptreStakedFlare} from "src/lib/sflr/LibSceptreStakedFlare.sol"; +import {LibSceptreStakedFlare, SFLR_CONTRACT} from "src/lib/sflr/LibSceptreStakedFlare.sol"; +import {IStakedFlr} from "src/interface/IStakedFlr.sol"; +import {ZeroSFLRRate} from "src/err/ErrFtso.sol"; uint256 constant BLOCK_NUMBER = 31843105; @@ -13,8 +15,22 @@ contract LibSceptreStakedFlareTest is Test { vm.createSelectFork(LibFork.rpcUrlFlare(vm), BLOCK_NUMBER); } + function externalGetSFLRPerFLR18() external view returns (uint256) { + return LibSceptreStakedFlare.getSFLRPerFLR18(); + } + function testGetSFLRPerFLR18() external view { uint256 rate18 = LibSceptreStakedFlare.getSFLRPerFLR18(); assertEq(rate18, 0.877817288626455057e18); } + + function testGetSFLRPerFLR18ZeroReverts() external { + vm.mockCall( + address(SFLR_CONTRACT), + abi.encodeWithSelector(IStakedFlr.getSharesByPooledFlr.selector, uint256(1e18)), + abi.encode(uint256(0)) + ); + vm.expectRevert(abi.encodeWithSelector(ZeroSFLRRate.selector)); + this.externalGetSFLRPerFLR18(); + } }