Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verify with single payment token #10603

Merged
merged 31 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e1e95e3
Flip fee tokens in report decoding
austinborn Sep 9, 2023
f6548d9
Use array of quotePayload
austinborn Sep 12, 2023
e2df7e1
Update interface to single quote payload
austinborn Sep 13, 2023
2e31ec1
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 13, 2023
838e072
Passing tests
austinborn Sep 13, 2023
ac409a0
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 13, 2023
3e57be0
Gas snapshot update
austinborn Sep 13, 2023
d225951
Update go gen files
austinborn Sep 13, 2023
52bd323
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 14, 2023
206cc95
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 14, 2023
7c93caa
Update integration test interfaces
austinborn Sep 14, 2023
8f57dcd
Prettify
austinborn Sep 14, 2023
06a4855
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 14, 2023
f7a4709
Merge develop into branch
austinborn Sep 14, 2023
3bc65f8
Update snapshot
austinborn Sep 14, 2023
5e53105
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 14, 2023
c575c18
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 14, 2023
985c17e
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 14, 2023
8ee8c3e
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 14, 2023
b67c646
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 14, 2023
34f3cd0
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 14, 2023
20467b3
Merge develop into branch
austinborn Sep 14, 2023
8ffc99d
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 16, 2023
d93c859
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 18, 2023
2a50221
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 18, 2023
66c0d51
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 18, 2023
7a0963f
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 19, 2023
280acd0
Change second parameter name to parameterPayload
austinborn Sep 19, 2023
00a5d09
Prettier
austinborn Sep 19, 2023
7bed387
feePayload -> parameterPayload in integration tests
austinborn Sep 19, 2023
e58b869
Merge branch 'develop' into verify-single-payment-token
austinborn Sep 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
263 changes: 129 additions & 134 deletions contracts/gas-snapshots/llo-feeds.gas-snapshot

Large diffs are not rendered by default.

14 changes: 10 additions & 4 deletions contracts/src/v0.8/llo-feeds/VerifierProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -121,24 +121,30 @@ contract VerifierProxy is IVerifierProxy, ConfirmedOwner, TypeAndVersionInterfac
}

/// @inheritdoc IVerifierProxy
function verify(bytes calldata payload) external payable checkAccess returns (bytes memory) {
function verify(
bytes calldata payload,
bytes calldata feePayload
austinborn marked this conversation as resolved.
Show resolved Hide resolved
) external payable checkAccess returns (bytes memory) {
IVerifierFeeManager feeManager = s_feeManager;

// Bill the verifier
if (address(feeManager) != address(0)) {
feeManager.processFee{value: msg.value}(payload, msg.sender);
feeManager.processFee{value: msg.value}(payload, feePayload, msg.sender);
}

return _verify(payload);
}

/// @inheritdoc IVerifierProxy
function verifyBulk(bytes[] calldata payloads) external payable checkAccess returns (bytes[] memory verifiedReports) {
function verifyBulk(
bytes[] calldata payloads,
bytes calldata feePayload
) external payable checkAccess returns (bytes[] memory verifiedReports) {
IVerifierFeeManager feeManager = s_feeManager;

// Bill the verifier
if (address(feeManager) != address(0)) {
feeManager.processFeeBulk{value: msg.value}(payloads, msg.sender);
feeManager.processFeeBulk{value: msg.value}(payloads, feePayload, msg.sender);
}

//verify the reports
Expand Down
39 changes: 23 additions & 16 deletions contracts/src/v0.8/llo-feeds/dev/FeeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,16 @@ contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface {
}

/// @inheritdoc IVerifierFeeManager
function processFee(bytes calldata payload, address subscriber) external payable override onlyProxy {
(Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _processFee(payload, subscriber);
function processFee(
bytes calldata payload,
bytes calldata feePayload,
address subscriber
) external payable override onlyProxy {
(Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _processFee(
payload,
feePayload,
subscriber
);

if (fee.amount == 0) {
_tryReturnChange(subscriber, msg.value);
Expand All @@ -188,7 +196,11 @@ contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface {
}

/// @inheritdoc IVerifierFeeManager
function processFeeBulk(bytes[] calldata payloads, address subscriber) external payable override onlyProxy {
function processFeeBulk(
bytes[] calldata payloads,
bytes calldata feePayload,
address subscriber
) external payable override onlyProxy {
FeeAndReward[] memory feesAndRewards = new IFeeManager.FeeAndReward[](payloads.length);

//keep track of the number of fees to prevent over initialising the FeePayment array within _convertToLinkAndNativeFees
Expand All @@ -199,6 +211,7 @@ contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface {
for (uint256 i; i < payloads.length; ++i) {
(Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _processFee(
payloads[i],
feePayload,
subscriber
);

Expand Down Expand Up @@ -232,7 +245,7 @@ contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface {
function getFeeAndReward(
address subscriber,
bytes memory report,
Quote memory quote
address quoteAddress
) public view returns (Common.Asset memory, Common.Asset memory, uint256) {
Common.Asset memory fee;
Common.Asset memory reward;
Expand All @@ -251,7 +264,7 @@ contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface {
}

//verify the quote payload is a supported token
if (quote.quoteAddress != i_nativeAddress && quote.quoteAddress != i_linkAddress) {
if (quoteAddress != i_nativeAddress && quoteAddress != i_linkAddress) {
revert InvalidQuote();
}

Expand All @@ -270,14 +283,14 @@ contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface {
}

//get the discount being applied
uint256 discount = s_subscriberDiscounts[subscriber][feedId][quote.quoteAddress];
uint256 discount = s_subscriberDiscounts[subscriber][feedId][quoteAddress];

//the reward is always set in LINK
reward.assetAddress = i_linkAddress;
reward.amount = Math.ceilDiv(linkQuantity * (PERCENTAGE_SCALAR - discount), PERCENTAGE_SCALAR);

//calculate either the LINK fee or native fee if it's within the report
if (quote.quoteAddress == i_linkAddress) {
if (quoteAddress == i_linkAddress) {
fee.assetAddress = i_linkAddress;
fee.amount = reward.amount;
} else {
Expand Down Expand Up @@ -358,6 +371,7 @@ contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface {

function _processFee(
bytes calldata payload,
bytes calldata quotePayload,
address subscriber
) internal view returns (Common.Asset memory, Common.Asset memory, uint256) {
if (subscriber == address(this)) revert InvalidAddress();
Expand All @@ -369,17 +383,10 @@ contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface {
bytes32 feedId = bytes32(report);

//v1 doesn't need a quote payload, so skip the decoding
Quote memory quote;
address quote;
if (_getReportVersion(feedId) != REPORT_V1) {
//all reports greater than v1 should have a quote payload
(, , , , , bytes memory quoteBytes) = abi.decode(
payload,
// reportContext, report, rs, ss, raw, quote
(bytes32[3], bytes, bytes32[], bytes32[], bytes32, bytes)
);

//decode the quote from the bytes
(quote) = abi.decode(quoteBytes, (Quote));
(quote) = abi.decode(quotePayload, (address));
}

//decode the fee, it will always be native or LINK
Expand Down
4 changes: 2 additions & 2 deletions contracts/src/v0.8/llo-feeds/dev/interfaces/IFeeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ interface IFeeManager is IERC165, IVerifierFeeManager {
* @notice Calculate the applied fee and the reward from a report. If the sender is a subscriber, they will receive a discount.
* @param subscriber address trying to verify
* @param report report to calculate the fee for
* @param quote any metadata required to fetch the fee
* @param quoteAddress address of the quote payment token
* @return (fee, reward, totalDiscount) fee and the reward data with the discount applied
*/
function getFeeAndReward(
address subscriber,
bytes memory report,
Quote memory quote
address quoteAddress
) external returns (Common.Asset memory, Common.Asset memory, uint256);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@ import {Common} from "../../../libraries/Common.sol";
interface IVerifierFeeManager is IERC165 {
/**
* @notice Handles fees for a report from the subscriber and manages rewards
* @param payload report and quote to process the fee for
* @param payload report to process the fee for
* @param feePayload fee payload
* @param subscriber address of the fee will be applied
*/
function processFee(bytes calldata payload, address subscriber) external payable;
function processFee(bytes calldata payload, bytes calldata feePayload, address subscriber) external payable;

/**
* @notice Processes the fees for each report in the payload, billing the subscriber and paying the reward manager
* @param payloads reports and quotes to process
* @param payloads reports to process
* @param feePayload fee payload
* @param subscriber address of the user to process fee for
*/
function processFeeBulk(bytes[] calldata payloads, address subscriber) external payable;
function processFeeBulk(bytes[] calldata payloads, bytes calldata feePayload, address subscriber) external payable;

/**
* @notice Sets the fee recipients according to the fee manager
Expand Down
16 changes: 12 additions & 4 deletions contracts/src/v0.8/llo-feeds/interfaces/IVerifierProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,27 @@ interface IVerifierProxy {
* @notice Verifies that the data encoded has been signed
* correctly by routing to the correct verifier, and bills the user if applicable.
* @param payload The encoded data to be verified, including the signed
* report and any metadata for billing.
* report.
* @param feePayload fee metadata for billing
* @return verifierResponse The encoded report from the verifier.
*/
function verify(bytes calldata payload) external payable returns (bytes memory verifierResponse);
function verify(
bytes calldata payload,
bytes calldata feePayload
) external payable returns (bytes memory verifierResponse);

/**
* @notice Bulk verifies that the data encoded has been signed
* correctly by routing to the correct verifier, and bills the user if applicable.
* @param payloads The encoded payloads to be verified, including the signed
* report and any metadata for billing.
* report.
* @param feePayload fee metadata for billing
* @return verifiedReports The encoded reports from the verifier.
*/
function verifyBulk(bytes[] calldata payloads) external payable returns (bytes[] memory verifiedReports);
function verifyBulk(
bytes[] calldata payloads,
bytes calldata feePayload
) external payable returns (bytes[] memory verifiedReports);

/**
* @notice Sets the verifier address initially, allowing `setVerifier` to be set by this Verifier in the future
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ contract BaseFeeManagerTest is Test {
native = new WERC20Mock();

feeManagerProxy = new FeeManagerProxy();
rewardManager = new RewardManager(getLinkAddress());
feeManager = new FeeManager(getLinkAddress(), getNativeAddress(), address(feeManagerProxy), address(rewardManager));
rewardManager = new RewardManager(address(link));
feeManager = new FeeManager(address(link), address(native), address(feeManagerProxy), address(rewardManager));

//link the feeManager to the proxy
feeManagerProxy.setFeeManager(feeManager);
Expand Down Expand Up @@ -154,33 +154,21 @@ contract BaseFeeManagerTest is Test {
}

// solium-disable-next-line no-unused-vars
function getFee(
bytes memory report,
IFeeManager.Quote memory quote,
address subscriber
) public view returns (Common.Asset memory) {
function getFee(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) {
//get the fee
(Common.Asset memory fee, , ) = feeManager.getFeeAndReward(subscriber, report, quote);

return fee;
}

function getReward(
bytes memory report,
IFeeManager.Quote memory quote,
address subscriber
) public view returns (Common.Asset memory) {
function getReward(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) {
//get the reward
(, Common.Asset memory reward, ) = feeManager.getFeeAndReward(subscriber, report, quote);

return reward;
}

function getAppliedDiscount(
bytes memory report,
IFeeManager.Quote memory quote,
address subscriber
) public view returns (uint256) {
function getAppliedDiscount(bytes memory report, address quote, address subscriber) public view returns (uint256) {
//get the reward
(, , uint256 appliedDiscount) = feeManager.getFeeAndReward(subscriber, report, quote);

Expand Down Expand Up @@ -239,12 +227,12 @@ contract BaseFeeManagerTest is Test {
);
}

function getLinkQuote() public view returns (IFeeManager.Quote memory) {
return IFeeManager.Quote(getLinkAddress());
function getLinkQuote() public view returns (address) {
return address(link);
}

function getNativeQuote() public view returns (IFeeManager.Quote memory) {
return IFeeManager.Quote(getNativeAddress());
function getNativeQuote() public view returns (address) {
return address(native);
}

function withdraw(address assetAddress, address recipient, uint256 amount, address sender) public {
Expand Down Expand Up @@ -302,6 +290,7 @@ contract BaseFeeManagerTest is Test {
function ProcessFeeAsUser(
bytes memory payload,
address subscriber,
address tokenAddress,
uint256 wrappedNativeValue,
address sender
) public {
Expand All @@ -310,50 +299,43 @@ contract BaseFeeManagerTest is Test {
changePrank(sender);

//process the fee
feeManager.processFee{value: wrappedNativeValue}(payload, subscriber);
feeManager.processFee{value: wrappedNativeValue}(payload, abi.encode(tokenAddress), subscriber);

//change ProcessFeeAsUserback to the original address
changePrank(originalAddr);
}

function processFee(bytes memory payload, address subscriber, uint256 wrappedNativeValue) public {
function processFee(bytes memory payload, address subscriber, address feeAddress, uint256 wrappedNativeValue) public {
//record the current address and switch to the recipient
address originalAddr = msg.sender;
changePrank(subscriber);

//process the fee
feeManagerProxy.processFee{value: wrappedNativeValue}(payload);
feeManagerProxy.processFee{value: wrappedNativeValue}(payload, abi.encode(feeAddress));

//change back to the original address
changePrank(originalAddr);
}

function processFee(bytes[] memory payloads, address subscriber, uint256 wrappedNativeValue) public {
function processFee(
bytes[] memory payloads,
address subscriber,
address feeAddress,
uint256 wrappedNativeValue
) public {
//record the current address and switch to the recipient
address originalAddr = msg.sender;
changePrank(subscriber);

//process the fee
feeManagerProxy.processFeeBulk{value: wrappedNativeValue}(payloads);
feeManagerProxy.processFeeBulk{value: wrappedNativeValue}(payloads, abi.encode(feeAddress));

//change back to the original address
changePrank(originalAddr);
}

function getPayload(bytes memory reportPayload, bytes memory quotePayload) public pure returns (bytes memory) {
return
abi.encode(
[DEFAULT_CONFIG_DIGEST, 0, 0],
reportPayload,
new bytes32[](1),
new bytes32[](1),
bytes32(""),
quotePayload
);
}

function getQuotePayload(address quoteAddress) public pure returns (bytes memory) {
return abi.encode(quoteAddress);
function getPayload(bytes memory reportPayload) public pure returns (bytes memory) {
return abi.encode([DEFAULT_CONFIG_DIGEST, 0, 0], reportPayload, new bytes32[](1), new bytes32[](1), bytes32(""));
}

function approveLink(address spender, uint256 quantity, address sender) public {
Expand All @@ -380,14 +362,6 @@ contract BaseFeeManagerTest is Test {
changePrank(originalAddr);
}

function getLinkAddress() public view returns (address) {
return address(link);
}

function getNativeAddress() public view returns (address) {
return address(native);
}

function payLinkDeficit(bytes32 configDigest, address sender) public {
//record the current address and switch to the recipient
address originalAddr = msg.sender;
Expand Down
Loading
Loading