diff --git a/contracts/EVMBundler.sol b/contracts/EVMBundler.sol index 9b7a6639..4c84be46 100644 --- a/contracts/EVMBundler.sol +++ b/contracts/EVMBundler.sol @@ -11,5 +11,5 @@ import {ERC4626Bundler} from "./ERC4626Bundler.sol"; /// @custom:contact security@morpho.org /// @notice Common bundler layer guaranteeing it can be deployed to the same address on all EVM-compatible chains. contract EVMBundler is Permit2Bundler, ERC4626Bundler, URDBundler, MorphoBundler { - constructor(address urd, address morpho) URDBundler(urd) MorphoBundler(morpho) {} + constructor(address morpho) MorphoBundler(morpho) {} } diff --git a/contracts/URDBundler.sol b/contracts/URDBundler.sol index e6207fd9..322564a9 100644 --- a/contracts/URDBundler.sol +++ b/contracts/URDBundler.sol @@ -12,21 +12,14 @@ import {BaseBundler} from "./BaseBundler.sol"; /// @custom:contact security@morpho.xyz /// @notice Bundler that allows to claim token rewards on the Universal Rewards Distributor. contract URDBundler is BaseBundler { - IUniversalRewardsDistributor public immutable URD; - - constructor(address urd) { - require(urd != address(0), ErrorsLib.ZERO_ADDRESS); - - URD = IUniversalRewardsDistributor(urd); - } - - function claim(uint256 distributionId, address account, address reward, uint256 claimable, bytes32[] calldata proof) + function claim(address distributor, address account, address reward, uint256 claimable, bytes32[] calldata proof) external payable { + require(distributor != address(0), ErrorsLib.ZERO_ADDRESS); require(account != address(0), ErrorsLib.ZERO_ADDRESS); require(account != address(this), ErrorsLib.BUNDLER_ADDRESS); - URD.claim(distributionId, account, reward, claimable, proof); + IUniversalRewardsDistributor(distributor).claim(account, reward, claimable, proof); } } diff --git a/contracts/ethereum-mainnet/EthereumBundler.sol b/contracts/ethereum-mainnet/EthereumBundler.sol index 2750f442..ccd5a68b 100644 --- a/contracts/ethereum-mainnet/EthereumBundler.sol +++ b/contracts/ethereum-mainnet/EthereumBundler.sol @@ -14,5 +14,5 @@ import {WNativeBundler} from "../WNativeBundler.sol"; contract EthereumBundler is EVMBundler, WNativeBundler, StEthBundler { /* CONSTRUCTOR */ - constructor(address urd, address morpho) EVMBundler(urd, morpho) WNativeBundler(WETH) {} + constructor(address morpho) EVMBundler(morpho) WNativeBundler(WETH) {} } diff --git a/lib/morpho-blue b/lib/morpho-blue index 60e6af13..08472125 160000 --- a/lib/morpho-blue +++ b/lib/morpho-blue @@ -1 +1 @@ -Subproject commit 60e6af136403962ec18fef98b3fbf49d064c11e6 +Subproject commit 084721252cca3c40b8c289837b9ed3a33e54b36c diff --git a/lib/universal-rewards-distributor b/lib/universal-rewards-distributor index 426ad796..af5c6981 160000 --- a/lib/universal-rewards-distributor +++ b/lib/universal-rewards-distributor @@ -1 +1 @@ -Subproject commit 426ad7969840e82a76df24fd4eb5a7d2378accd4 +Subproject commit af5c69815a6cfff532829001573443395443d73b diff --git a/test/forge/EVMBundlerLocalTest.sol b/test/forge/EVMBundlerLocalTest.sol index 6825e7c5..10841e56 100644 --- a/test/forge/EVMBundlerLocalTest.sol +++ b/test/forge/EVMBundlerLocalTest.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import {UniversalRewardsDistributor} from "@universal-rewards-distributor/UniversalRewardsDistributor.sol"; +import {UrdFactory} from "@universal-rewards-distributor/UrdFactory.sol"; import {SigUtils} from "./helpers/SigUtils.sol"; import {ErrorsLib} from "contracts/libraries/ErrorsLib.sol"; @@ -22,7 +23,7 @@ contract EVMBundlerLocalTest is LocalTest { uint256 internal constant SIG_DEADLINE = type(uint32).max; - UniversalRewardsDistributor private urd; + UrdFactory private factory; EVMBundler private bundler; bytes[] private bundle; @@ -32,8 +33,8 @@ contract EVMBundlerLocalTest is LocalTest { function setUp() public override { super.setUp(); - urd = new UniversalRewardsDistributor(); - bundler = new EVMBundler(address(urd),address(morpho)); + factory = new UrdFactory(); + bundler = new EVMBundler(address(morpho)); merkle = new Merkle(); vm.startPrank(USER); @@ -783,21 +784,34 @@ contract EVMBundlerLocalTest is LocalTest { /* TESTS URDBUNDLER */ - function testClaimRewardsZeroAddress(uint256 claimable) public { + function testClaimRewardsZeroAddressDistribution(uint256 claimable, address account) public { + vm.assume(account != address(0)); + claimable = bound(claimable, MIN_AMOUNT, MAX_AMOUNT); + + bytes32[] memory proof; + + bundle.push(abi.encodeCall(URDBundler.claim, (address(0), account, address(borrowableToken), claimable, proof))); + + vm.prank(USER); + vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); + bundler.multicall(block.timestamp, bundle); + } + + function testClaimRewardsZeroAddressAccount(uint256 claimable) public { claimable = bound(claimable, MIN_AMOUNT, MAX_AMOUNT); bytes32 root; bytes32[] memory proof; - uint256 distribution = urd.createDistribution(0, root); + address distributor = factory.createUrd(OWNER, 0, root, hex"", hex""); - bytes[] memory zeroAddressdata = new bytes[](1); - zeroAddressdata[0] = - abi.encodeCall(URDBundler.claim, (distribution, address(0), address(borrowableToken), claimable, proof)); + bundle.push( + abi.encodeCall(URDBundler.claim, (distributor, address(0), address(borrowableToken), claimable, proof)) + ); vm.prank(USER); vm.expectRevert(bytes(ErrorsLib.ZERO_ADDRESS)); - bundler.multicall(block.timestamp, zeroAddressdata); + bundler.multicall(block.timestamp, bundle); } function testClaimRewardsBundlerAddress(uint256 claimable) public { @@ -806,16 +820,17 @@ contract EVMBundlerLocalTest is LocalTest { bytes32 root; bytes32[] memory proof; - uint256 distribution = urd.createDistribution(0, root); + address distributor = factory.createUrd(OWNER, 0, root, hex"", hex""); - bytes[] memory bundlerAddressdata = new bytes[](1); - bundlerAddressdata[0] = abi.encodeCall( - URDBundler.claim, (distribution, address(bundler), address(borrowableToken), claimable, proof) + bundle.push( + abi.encodeCall( + URDBundler.claim, (distributor, address(bundler), address(borrowableToken), claimable, proof) + ) ); vm.prank(USER); vm.expectRevert(bytes(ErrorsLib.BUNDLER_ADDRESS)); - bundler.multicall(block.timestamp, bundlerAddressdata); + bundler.multicall(block.timestamp, bundle); } function testClaimRewards(uint256 claimable, uint8 size) public { @@ -824,26 +839,27 @@ contract EVMBundlerLocalTest is LocalTest { (bytes32[] memory proofs, bytes32 root) = _setupRewards(claimable, boundedSize); - borrowableToken.setBalance(address(this), claimable); - borrowableToken.approve(address(urd), type(uint256).max); - collateralToken.setBalance(address(this), claimable); - collateralToken.approve(address(urd), type(uint256).max); + address distributor = factory.createUrd(OWNER, 0, root, hex"", hex""); - uint256 distribution = urd.createDistribution(0, root); + borrowableToken.setBalance(distributor, claimable); + collateralToken.setBalance(distributor, claimable); bytes32[] memory borrowableTokenProof = merkle.getProof(proofs, 0); bytes32[] memory collateralTokenProof = merkle.getProof(proofs, 1); - bytes[] memory data = new bytes[](2); - data[0] = abi.encodeCall( - URDBundler.claim, (distribution, USER, address(borrowableToken), claimable, borrowableTokenProof) + bundle.push( + abi.encodeCall( + URDBundler.claim, (distributor, USER, address(borrowableToken), claimable, borrowableTokenProof) + ) ); - data[1] = abi.encodeCall( - URDBundler.claim, (distribution, USER, address(collateralToken), claimable, collateralTokenProof) + bundle.push( + abi.encodeCall( + URDBundler.claim, (distributor, USER, address(collateralToken), claimable, collateralTokenProof) + ) ); vm.prank(USER); - bundler.multicall(block.timestamp, data); + bundler.multicall(block.timestamp, bundle); assertEq(borrowableToken.balanceOf(USER), claimable, "User's borrowable balance"); assertEq(collateralToken.balanceOf(USER), claimable, "User's collateral balance"); diff --git a/test/forge/ethereum-mainnet/EthereumBundlerEthereumTest.sol b/test/forge/ethereum-mainnet/EthereumBundlerEthereumTest.sol index f7ef9502..b660b676 100644 --- a/test/forge/ethereum-mainnet/EthereumBundlerEthereumTest.sol +++ b/test/forge/ethereum-mainnet/EthereumBundlerEthereumTest.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import {IAllowanceTransfer} from "@permit2/interfaces/IAllowanceTransfer.sol"; import {ECDSA} from "@openzeppelin/utils/cryptography/ECDSA.sol"; -import {UniversalRewardsDistributor} from "@universal-rewards-distributor/UniversalRewardsDistributor.sol"; import "contracts/ethereum-mainnet/EthereumBundler.sol"; import {MorphoBundler} from "contracts/MorphoBundler.sol"; @@ -19,14 +18,12 @@ contract EthereumBundlerEthereumTest is EthereumTest { using MarketParamsLib for MarketParams; using SafeTransferLib for ERC20; - UniversalRewardsDistributor private urd; EthereumBundler private bundler; function setUp() public override { super.setUp(); - urd = new UniversalRewardsDistributor(); - bundler = new EthereumBundler(address(urd), address(morpho)); + bundler = new EthereumBundler(address(morpho)); vm.prank(USER); morpho.setAuthorization(address(bundler), true);