feat(entropy_contracts): don't call an address if it is an Eoa in reveal callback (#1395)

* don't call an address if it is an Eoa

* fix comment

* update comment
This commit is contained in:
Dev Kalra 2024-03-28 14:12:36 +05:30 committed by GitHub
parent 0e6484daca
commit 02e196e924
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 60 additions and 11 deletions

View File

@ -364,8 +364,9 @@ abstract contract Entropy is IEntropy, EntropyState {
} }
// Fulfill a request for a random number and call back the requester. This method validates the provided userRandomness // Fulfill a request for a random number and call back the requester. This method validates the provided userRandomness
// and provider's revelation against the corresponding commitment in the in-flight request. If both values are validated, // and provider's revelation against the corresponding commitment in the in-flight request. If both values are validated
// this function calls the requester's entropyCallback method with the sequence number and the random number as arguments. // and the requestor address is a contract address, this function calls the requester's entropyCallback method with the
// sequence number and the random number as arguments. Else if the requestor is an EOA, it won't call it.
// //
// Note that this function can only be called once per in-flight request. Calling this function deletes the stored // Note that this function can only be called once per in-flight request. Calling this function deletes the stored
// request information (so that the contract doesn't use a linear amount of storage in the number of requests). // request information (so that the contract doesn't use a linear amount of storage in the number of requests).
@ -405,11 +406,18 @@ abstract contract Entropy is IEntropy, EntropyState {
clearRequest(provider, sequenceNumber); clearRequest(provider, sequenceNumber);
IEntropyConsumer(callAddress)._entropyCallback( // Check if the callAddress is a contract account.
sequenceNumber, uint len;
provider, assembly {
randomNumber len := extcodesize(callAddress)
); }
if (len != 0) {
IEntropyConsumer(callAddress)._entropyCallback(
sequenceNumber,
provider,
randomNumber
);
}
} }
function getProviderInfo( function getProviderInfo(

View File

@ -799,7 +799,7 @@ contract EntropyTest is Test, EntropyTestUtils, EntropyEvents {
vm.stopPrank(); vm.stopPrank();
} }
function testRequestWithCallbackAndRevealWithCallback() public { function testRequestWithCallbackAndRevealWithCallbackByContract() public {
bytes32 userRandomNumber = bytes32(uint(42)); bytes32 userRandomNumber = bytes32(uint(42));
uint fee = random.getFee(provider1); uint fee = random.getFee(provider1);
EntropyConsumer consumer = new EntropyConsumer(address(random)); EntropyConsumer consumer = new EntropyConsumer(address(random));
@ -853,6 +853,46 @@ contract EntropyTest is Test, EntropyTestUtils, EntropyEvents {
assertEq(reqAfterReveal.sequenceNumber, 0); assertEq(reqAfterReveal.sequenceNumber, 0);
} }
function testRequestWithCallbackAndRevealWithCallbackByEoa() public {
bytes32 userRandomNumber = bytes32(uint(42));
uint fee = random.getFee(provider1);
vm.deal(user1, fee);
vm.prank(user1);
uint64 assignedSequenceNumber = random.requestWithCallback{value: fee}(
provider1,
userRandomNumber
);
EntropyStructs.Request memory req = random.getRequest(
provider1,
assignedSequenceNumber
);
bytes32 blockHash = bytes32(uint256(0));
vm.expectEmit(false, false, false, true, address(random));
emit RevealedWithCallback(
req,
userRandomNumber,
provider1Proofs[assignedSequenceNumber],
random.combineRandomValues(
userRandomNumber,
provider1Proofs[assignedSequenceNumber],
0
)
);
random.revealWithCallback(
provider1,
assignedSequenceNumber,
userRandomNumber,
provider1Proofs[assignedSequenceNumber]
);
EntropyStructs.Request memory reqAfterReveal = random.getRequest(
provider1,
assignedSequenceNumber
);
assertEq(reqAfterReveal.sequenceNumber, 0);
}
function testRequestAndRevealWithCallback() public { function testRequestAndRevealWithCallback() public {
uint64 sequenceNumber = request(user2, provider1, 42, false); uint64 sequenceNumber = request(user2, provider1, 42, false);
assertEq(random.getRequest(provider1, sequenceNumber).requester, user2); assertEq(random.getRequest(provider1, sequenceNumber).requester, user2);

View File

@ -51,9 +51,10 @@ interface IEntropy is EntropyEvents {
bytes32 userRandomNumber bytes32 userRandomNumber
) external payable returns (uint64 assignedSequenceNumber); ) external payable returns (uint64 assignedSequenceNumber);
// Fulfill a request for a random number. This method validates the provided userRevelation and provider's proof // Fulfill a request for a random number and call back the requester. This method validates the provided userRandomness
// against the corresponding commitments in the in-flight request. If both values are validated, this function returns // and provider's revelation against the corresponding commitment in the in-flight request. If both values are validated
// the corresponding random number. // and the requestor address is a contract address, this function calls the requester's entropyCallback method with the
// sequence number and the random number as arguments. Else if the requestor is an EOA, it won't call it.
// //
// Note that this function can only be called once per in-flight request. Calling this function deletes the stored // Note that this function can only be called once per in-flight request. Calling this function deletes the stored
// request information (so that the contract doesn't use a linear amount of storage in the number of requests). // request information (so that the contract doesn't use a linear amount of storage in the number of requests).