feat: add guarded Base Sepolia encore

This commit is contained in:
golem
2026-08-21 16:01:35 -06:00
parent 94f2ad6e09
commit 90b0a11b8a
16 changed files with 784 additions and 25 deletions
+75 -4
View File
@@ -20,6 +20,7 @@ abstract contract DemoScript is Script {
error InvalidDeploymentBlock();
error InvalidManifestSchema(uint256 schemaVersion);
error InvalidActorConfiguration();
error InvalidPublicRpcUrl();
error UnexpectedState(string label, uint256 expected, uint256 actual);
error UnexpectedAddress(string label, address expected, address actual);
@@ -60,6 +61,72 @@ abstract contract DemoScript is Script {
return vm.envOr("DEPLOYMENT_MANIFEST_PATH", defaultPath);
}
function _requireBaseSender(address scriptSender) internal view returns (address sender) {
sender = vm.envAddress("BASE_SEPOLIA_SENDER");
_assertAddress("BASE_SEPOLIA_SENDER", scriptSender, sender);
}
function _requireBaseConfig(address scriptSender)
internal
view
returns (address sender, address recipient, string memory publicRpcUrl)
{
sender = _requireBaseSender(scriptSender);
recipient = vm.envAddress("BASE_SEPOLIA_RECIPIENT");
if (sender == address(0) || recipient == address(0) || sender == recipient) revert InvalidActorConfiguration();
publicRpcUrl = vm.envString("BASE_SEPOLIA_PUBLIC_RPC_URL");
_requirePublicHttpsUrl(publicRpcUrl);
}
function _requirePublicHttpsUrl(string memory value) internal pure {
bytes memory url = bytes(value);
bytes memory prefix = bytes("https://");
if (url.length <= prefix.length) revert InvalidPublicRpcUrl();
for (uint256 i; i < prefix.length; ++i) {
if (url[i] != prefix[i]) revert InvalidPublicRpcUrl();
}
bool query;
uint256 queryStart;
for (uint256 i = prefix.length; i < url.length; ++i) {
bytes1 character = url[i];
if (!query && character == "@") revert InvalidPublicRpcUrl();
if (character == "?") {
query = true;
queryStart = i + 1;
break;
}
if (character == "#") break;
}
if (!query) return;
bytes memory lowered = new bytes(url.length - queryStart);
for (uint256 i; i < lowered.length; ++i) {
uint8 character = uint8(url[queryStart + i]);
lowered[i] = character >= 65 && character <= 90 ? bytes1(character + 32) : bytes1(character);
}
if (
_containsBytes(lowered, bytes("key=")) || _containsBytes(lowered, bytes("token="))
|| _containsBytes(lowered, bytes("secret=")) || _containsBytes(lowered, bytes("password="))
|| _containsBytes(lowered, bytes("credential="))
) revert InvalidPublicRpcUrl();
}
function _containsBytes(bytes memory haystack, bytes memory needle) private pure returns (bool) {
if (needle.length > haystack.length) return false;
for (uint256 i; i + needle.length <= haystack.length; ++i) {
bool matches = true;
for (uint256 j; j < needle.length; ++j) {
if (haystack[i + j] != needle[j]) {
matches = false;
break;
}
}
if (matches) return true;
}
return false;
}
function _readManifest(string memory path, bool active) internal view returns (Manifest memory manifest) {
string memory json = vm.readFile(path);
_assertExactManifestSchema(json);
@@ -112,7 +179,7 @@ abstract contract DemoScript is Script {
}
function _parseActors(string memory json, uint256 chainId) private view returns (Actor[] memory actors) {
uint256 actorCount = chainId == ANVIL_CHAIN_ID ? 3 : 1;
uint256 actorCount = chainId == ANVIL_CHAIN_ID ? 3 : 2;
actors = new Actor[](actorCount);
for (uint256 i; i < actorCount; ++i) {
string memory index = vm.toString(i);
@@ -157,9 +224,13 @@ abstract contract DemoScript is Script {
}
if (
manifest.chainId != BASE_SEPOLIA_CHAIN_ID || manifest.actors.length != 1
|| !_equals(manifest.network, "baseSepolia") || !_equals(manifest.actors[0].label, "owner")
|| manifest.actors[0].address_ != manifest.owner
manifest.chainId != BASE_SEPOLIA_CHAIN_ID || manifest.actors.length != 2
|| !_equals(manifest.network, "baseSepolia") || !_equals(manifest.actors[0].label, "Presenter")
|| !_equals(manifest.actors[1].label, "Recipient") || manifest.actors[0].address_ != manifest.owner
) revert InvalidActorConfiguration();
if (
manifest.actors[0].address_ == address(0) || manifest.actors[1].address_ == address(0)
|| manifest.actors[0].address_ == manifest.actors[1].address_
) revert InvalidActorConfiguration();
}