Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
246 changes: 246 additions & 0 deletions target_chains/ethereum/contracts/test/MockEntropy.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "@pythnetwork/entropy-sdk-solidity/MockEntropy.sol";
import "@pythnetwork/entropy-sdk-solidity/IEntropyConsumer.sol";
import "@pythnetwork/entropy-sdk-solidity/EntropyStructsV2.sol";

contract MockEntropyConsumer is IEntropyConsumer {
address public entropy;
bytes32 public lastRandomNumber;
uint64 public lastSequenceNumber;
address public lastProvider;
uint256 public callbackCount;

constructor(address _entropy) {
entropy = _entropy;
}

function requestRandomNumber() external payable returns (uint64) {
return MockEntropy(entropy).requestV2{value: msg.value}();
}

function requestRandomNumberWithGasLimit(
uint32 gasLimit
) external payable returns (uint64) {
return MockEntropy(entropy).requestV2{value: msg.value}(gasLimit);
}

function requestRandomNumberFromProvider(
address provider,
uint32 gasLimit
) external payable returns (uint64) {
return
MockEntropy(entropy).requestV2{value: msg.value}(
provider,
gasLimit
);
}

function getEntropy() internal view override returns (address) {
return entropy;
}

function entropyCallback(
uint64 sequenceNumber,
address provider,
bytes32 randomNumber
) internal override {
lastSequenceNumber = sequenceNumber;
lastProvider = provider;
lastRandomNumber = randomNumber;
callbackCount += 1;
}
}

contract MockEntropyTest is Test {
MockEntropy public entropy;
MockEntropyConsumer public consumer;
address public provider;

function setUp() public {
provider = address(0x1234);
entropy = new MockEntropy(provider);
consumer = new MockEntropyConsumer(address(entropy));
}

function testBasicRequestAndReveal() public {
uint64 seq = consumer.requestRandomNumber();
assertEq(seq, 1, "Sequence number should be 1");

bytes32 randomNumber = bytes32(uint256(42));
entropy.mockReveal(provider, seq, randomNumber);

assertEq(
consumer.lastSequenceNumber(),
seq,
"Callback sequence number mismatch"
);
assertEq(
consumer.lastProvider(),
provider,
"Callback provider mismatch"
);
assertEq(
consumer.lastRandomNumber(),
randomNumber,
"Random number mismatch"
);
assertEq(consumer.callbackCount(), 1, "Callback should be called once");
}

function testDifferentInterleavings() public {
uint64 seq1 = consumer.requestRandomNumber();
uint64 seq2 = consumer.requestRandomNumber();
uint64 seq3 = consumer.requestRandomNumber();

assertEq(seq1, 1, "First sequence should be 1");
assertEq(seq2, 2, "Second sequence should be 2");
assertEq(seq3, 3, "Third sequence should be 3");

bytes32 random2 = bytes32(uint256(200));
bytes32 random3 = bytes32(uint256(300));
bytes32 random1 = bytes32(uint256(100));

entropy.mockReveal(provider, seq2, random2);
assertEq(
consumer.lastRandomNumber(),
random2,
"Should reveal seq2 first"
);
assertEq(consumer.lastSequenceNumber(), seq2, "Sequence should be 2");

entropy.mockReveal(provider, seq3, random3);
assertEq(
consumer.lastRandomNumber(),
random3,
"Should reveal seq3 second"
);
assertEq(consumer.lastSequenceNumber(), seq3, "Sequence should be 3");

entropy.mockReveal(provider, seq1, random1);
assertEq(
consumer.lastRandomNumber(),
random1,
"Should reveal seq1 last"
);
assertEq(consumer.lastSequenceNumber(), seq1, "Sequence should be 1");

assertEq(
consumer.callbackCount(),
3,
"All three callbacks should be called"
);
}

function testDifferentProviders() public {
address provider2 = address(0x5678);

uint64 seq1 = consumer.requestRandomNumberFromProvider(
provider,
100000
);
uint64 seq2 = consumer.requestRandomNumberFromProvider(
provider2,
100000
);

assertEq(seq1, 1, "Provider 1 first sequence should be 1");
assertEq(seq2, 1, "Provider 2 first sequence should be 1");

bytes32 random1 = bytes32(uint256(111));
bytes32 random2 = bytes32(uint256(222));

entropy.mockReveal(provider, seq1, random1);
assertEq(
consumer.lastRandomNumber(),
random1,
"First provider random number"
);

entropy.mockReveal(provider2, seq2, random2);
assertEq(
consumer.lastRandomNumber(),
random2,
"Second provider random number"
);
}

function testRequestWithGasLimit() public {
uint64 seq = consumer.requestRandomNumberWithGasLimit(200000);

assertEq(seq, 1, "Sequence should be 1");

EntropyStructsV2.Request memory req = entropy.getRequestV2(
provider,
seq
);
assertEq(req.gasLimit10k, 20, "Gas limit should be 20 (200k / 10k)");

bytes32 randomNumber = bytes32(uint256(999));
entropy.mockReveal(provider, seq, randomNumber);

assertEq(
consumer.lastRandomNumber(),
randomNumber,
"Random number should match"
);
}

function testGetProviderInfo() public {
EntropyStructsV2.ProviderInfo memory info = entropy.getProviderInfoV2(
provider
);
assertEq(info.feeInWei, 1, "Fee should be 1");
assertEq(
info.defaultGasLimit,
100000,
"Default gas limit should be 100000"
);
assertEq(info.sequenceNumber, 1, "Sequence number should start at 1");
}

function testGetDefaultProvider() public {
assertEq(
entropy.getDefaultProvider(),
provider,
"Default provider should match"
);
}

function testFeesReturnZero() public {
assertEq(entropy.getFeeV2(), 0, "getFeeV2() should return 0");
assertEq(
entropy.getFeeV2(100000),
0,
"getFeeV2(gasLimit) should return 0"
);
assertEq(
entropy.getFeeV2(provider, 100000),
0,
"getFeeV2(provider, gasLimit) should return 0"
);
}

function testCustomRandomNumbers() public {
uint64 seq = consumer.requestRandomNumber();

bytes32[] memory randomNumbers = new bytes32[](3);
randomNumbers[0] = bytes32(uint256(0));
randomNumbers[1] = bytes32(type(uint256).max);
randomNumbers[2] = keccak256("custom random value");

for (uint i = 0; i < randomNumbers.length; i++) {
if (i > 0) {
seq = consumer.requestRandomNumber();
}
entropy.mockReveal(provider, seq, randomNumbers[i]);
assertEq(
consumer.lastRandomNumber(),
randomNumbers[i],
"Custom random number should match"
);
}
}
}
Loading
Loading