Repository files navigation

Forward Proxy

Motivation

ForwardProxy is useful for permissioned smart contracts systems in environments where EOAs are not available (i.e.: tests written with ds-test) and there is a need to emulate different actors interacting with components of the system.
It can be thought of as a 1-out-of-∞ multisig to interact with other smart contracts.

AuthForwardProxy is an extension of ForwardPorxy that is useful for contracts whose permissioned methods should not be made completely permissionless by using ForwardProxy.
It can be thought of as a 1-out-of-N multisig to interact with other smart contracts.

How it works?

Both ForwardProxy and AuthForwardProxy provide a fallback function that forwards all calls to another contract using the EVM instruction call. The success and return data of the call will be returned back to the caller of the proxy.

Notice that this is different from OpenZeppelin's base Proxy contract, which uses delegatecall instead.

This largely alleviates the security issues that come with delegatecall, since the call to the target contract will be made on its own context, but this code has not been audited and I DO NOT recommend using it in production.

As it currently stands, this contract could be seen as a bare-bones permissionless 1-out-of-∞ multisig that allows interacting with smart contracts.

API

interfaceForwardProxyLike {
function __to() externalviewreturns (address);
function _() externalreturns (address);
}
  • __to(): returns the address of the target contract.
  • _(): updates the address of the target contract.

The methods have these peculiar names for 2 reasons:

  1. Keep it short, reducing the noise when reading the code.
  2. Minimize the chances of clashing names, which would prevent the proxy from working properly.

The setter method _() implements method chaining to make it more ergonomic:

Instead of:

proxy._(target);
Target(proxy).targetMethod();

You can write:

Target(proxy._(target)).targetMethod();

This is specially useful when the proxy needs to be used with multiple targets:

TargetA(proxy._(targetA)).targetAMethod();
TargetB(proxy._(targetB)).targetBMethod();

What about payable methods?

I'm glad you asked!

ForwardProxy/AuthForwardProxy also forward any ether sent through it to the target.

contractPayableTarget {
event A(addresswho, uint256wad);
function funcA() publicpayablereturns (address, uint256) {
emitA(msg.sender, msg.value);
return (msg.sender, msg.value);
}
receive() externalpayable {}
}
PayableTarget payableTarget =newPayableTarget();
(addresssender, uint256value) =PayableTarget(
proxy._(address(payableTarget))
).funcA{value: 20ether}();

However, it's NOT possible to make plain ether transfers to a ForwardProxy/AuthForwardProxy:

payable(proxy).transfer(1 ether); // This will REVERT!

Alright, show me the code!

ForwardProxy usr1 =newForwardProxy();
ForwardProxy usr2 =newForwardProxy();
System system =newSystem(/* ... */);
system.authorize(address(usr1), 'role-A');
system.authorize(address(usr2), 'role-B');
// "Impersonate" a contract of type `System`System(
// Set the `system` contract as the target `to` and gets the reference to the proxy address.
usr1._(address(system))
)
// Call a method in the proxy which will be forwarded to the system
.authorizedMethodA();
// Do the same for `usr2`:System(usr2._(address(system))).authorizedMethodB();

The example above is roughly equivalent to the following using ethers.js:

constusr1=newethers.Wallet('<private key 1>');constusr2=newethers.Wallet('<private key 2>');constsystem=newethers.Contract('<address>','<abi>');consttx1=awaitsystem.authorize(address(usr1),'role-A');awaittx1.wait()consttx2=awaitsystem.authorize(address(usr2),'role-B');awaittx2.wait()system.connect(usr1);consttx3=awaitsystem.authorizedMethodA();awaittx3.wait();system.connect(usr2);consttx4=awaitsystem.authorizedMethodB();awaittx4.wait();

How to authorize addresses in AuthForwardProxy?

Each address allowed into AuthForwarProxy is a ward. Once an address receives a ward status, it can add or remove other wards, but it cannot modify the owner. The owner has root access to the contract.

To avoid naming clashes with the target contract, every public function on AuthForwardProxy that is not part of the ForwardProxyLike interface is appended of its own selector:

interfaceAuthForwardProxyLike {
///@notice Get the owner of the contract.///@dev The selector for `owner()` is `0x8da5cb5b` and so on...function owner_8da5cb5b() externalviewreturns (address);
///@notice Transfer the ownership of the contract.function transferOwnership_f2fde38b(addresswho) external;
///@notice Give `who` the ward role.function rely_65fae35e(addresswho) external;
///@notice Revokes the ward role for `who`.function deny_9c52a7f1(addresswho) external;
///@notice Gets the ward status of `who`.function wards_bf353dbb(addresswho) externalviewreturns (uint256);
}

After deploying the contract, the owner can call rely_65fae35e(address) to authorize a different address:

seth send "$AUTH_FORWARD_PROXY_ADDRESS""rely_65fae35e(address)""$WARD_ADDRESS"

About

`ForwardProxy` provides a fallback function that forwards all calls to another contract using the EVM `call` instruction.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Forward Proxy

Motivation

ForwardProxy is useful for permissioned smart contracts systems in environments where EOAs are not available (i.e.: tests written with ds-test) and there is a need to emulate different actors interacting with components of the system.
It can be thought of as a 1-out-of-∞ multisig to interact with other smart contracts.

AuthForwardProxy is an extension of ForwardPorxy that is useful for contracts whose permissioned methods should not be made completely permissionless by using ForwardProxy.
It can be thought of as a 1-out-of-N multisig to interact with other smart contracts.

How it works?

Both ForwardProxy and AuthForwardProxy provide a fallback function that forwards all calls to another contract using the EVM instruction call. The success and return data of the call will be returned back to the caller of the proxy.

Notice that this is different from OpenZeppelin's base Proxy contract, which uses delegatecall instead.

This largely alleviates the security issues that come with delegatecall, since the call to the target contract will be made on its own context, but this code has not been audited and I DO NOT recommend using it in production.

As it currently stands, this contract could be seen as a bare-bones permissionless 1-out-of-∞ multisig that allows interacting with smart contracts.

API

interfaceForwardProxyLike {
function __to() externalviewreturns (address);
function _() externalreturns (address);
}
  • __to(): returns the address of the target contract.
  • _(): updates the address of the target contract.

The methods have these peculiar names for 2 reasons:

  1. Keep it short, reducing the noise when reading the code.
  2. Minimize the chances of clashing names, which would prevent the proxy from working properly.

The setter method _() implements method chaining to make it more ergonomic:

Instead of:

proxy._(target);
Target(proxy).targetMethod();

You can write:

Target(proxy._(target)).targetMethod();

This is specially useful when the proxy needs to be used with multiple targets:

TargetA(proxy._(targetA)).targetAMethod();
TargetB(proxy._(targetB)).targetBMethod();

What about payable methods?

I'm glad you asked!

ForwardProxy/AuthForwardProxy also forward any ether sent through it to the target.

contractPayableTarget {
event A(addresswho, uint256wad);
function funcA() publicpayablereturns (address, uint256) {
emitA(msg.sender, msg.value);
return (msg.sender, msg.value);
}
receive() externalpayable {}
}
PayableTarget payableTarget =newPayableTarget();
(addresssender, uint256value) =PayableTarget(
proxy._(address(payableTarget))
).funcA{value: 20ether}();

However, it's NOT possible to make plain ether transfers to a ForwardProxy/AuthForwardProxy:

payable(proxy).transfer(1 ether); // This will REVERT!

Alright, show me the code!

ForwardProxy usr1 =newForwardProxy();
ForwardProxy usr2 =newForwardProxy();
System system =newSystem(/* ... */);
system.authorize(address(usr1), 'role-A');
system.authorize(address(usr2), 'role-B');
// "Impersonate" a contract of type `System`System(
// Set the `system` contract as the target `to` and gets the reference to the proxy address.
usr1._(address(system))
)
// Call a method in the proxy which will be forwarded to the system
.authorizedMethodA();
// Do the same for `usr2`:System(usr2._(address(system))).authorizedMethodB();

The example above is roughly equivalent to the following using ethers.js:

constusr1=newethers.Wallet('<private key 1>');constusr2=newethers.Wallet('<private key 2>');constsystem=newethers.Contract('<address>','<abi>');consttx1=awaitsystem.authorize(address(usr1),'role-A');awaittx1.wait()consttx2=awaitsystem.authorize(address(usr2),'role-B');awaittx2.wait()system.connect(usr1);consttx3=awaitsystem.authorizedMethodA();awaittx3.wait();system.connect(usr2);consttx4=awaitsystem.authorizedMethodB();awaittx4.wait();

How to authorize addresses in AuthForwardProxy?

Each address allowed into AuthForwarProxy is a ward. Once an address receives a ward status, it can add or remove other wards, but it cannot modify the owner. The owner has root access to the contract.

To avoid naming clashes with the target contract, every public function on AuthForwardProxy that is not part of the ForwardProxyLike interface is appended of its own selector:

interfaceAuthForwardProxyLike {
///@notice Get the owner of the contract.///@dev The selector for `owner()` is `0x8da5cb5b` and so on...function owner_8da5cb5b() externalviewreturns (address);
///@notice Transfer the ownership of the contract.function transferOwnership_f2fde38b(addresswho) external;
///@notice Give `who` the ward role.function rely_65fae35e(addresswho) external;
///@notice Revokes the ward role for `who`.function deny_9c52a7f1(addresswho) external;
///@notice Gets the ward status of `who`.function wards_bf353dbb(addresswho) externalviewreturns (uint256);
}

After deploying the contract, the owner can call rely_65fae35e(address) to authorize a different address:

seth send "$AUTH_FORWARD_PROXY_ADDRESS""rely_65fae35e(address)""$WARD_ADDRESS"

About

`ForwardProxy` provides a fallback function that forwards all calls to another contract using the EVM `call` instruction.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Forward Proxy

Motivation

ForwardProxy is useful for permissioned smart contracts systems in environments where EOAs are not available (i.e.: tests written with ds-test) and there is a need to emulate different actors interacting with components of the system.
It can be thought of as a 1-out-of-∞ multisig to interact with other smart contracts.

AuthForwardProxy is an extension of ForwardPorxy that is useful for contracts whose permissioned methods should not be made completely permissionless by using ForwardProxy.
It can be thought of as a 1-out-of-N multisig to interact with other smart contracts.

How it works?

Both ForwardProxy and AuthForwardProxy provide a fallback function that forwards all calls to another contract using the EVM instruction call. The success and return data of the call will be returned back to the caller of the proxy.

Notice that this is different from OpenZeppelin's base Proxy contract, which uses delegatecall instead.

This largely alleviates the security issues that come with delegatecall, since the call to the target contract will be made on its own context, but this code has not been audited and I DO NOT recommend using it in production.

As it currently stands, this contract could be seen as a bare-bones permissionless 1-out-of-∞ multisig that allows interacting with smart contracts.

API

interfaceForwardProxyLike {
function __to() externalviewreturns (address);
function _() externalreturns (address);
}
  • __to(): returns the address of the target contract.
  • _(): updates the address of the target contract.

The methods have these peculiar names for 2 reasons:

  1. Keep it short, reducing the noise when reading the code.
  2. Minimize the chances of clashing names, which would prevent the proxy from working properly.

The setter method _() implements method chaining to make it more ergonomic:

Instead of:

proxy._(target);
Target(proxy).targetMethod();

You can write:

Target(proxy._(target)).targetMethod();

This is specially useful when the proxy needs to be used with multiple targets:

TargetA(proxy._(targetA)).targetAMethod();
TargetB(proxy._(targetB)).targetBMethod();

What about payable methods?

I'm glad you asked!

ForwardProxy/AuthForwardProxy also forward any ether sent through it to the target.

contractPayableTarget {
event A(addresswho, uint256wad);
function funcA() publicpayablereturns (address, uint256) {
emitA(msg.sender, msg.value);
return (msg.sender, msg.value);
}
receive() externalpayable {}
}
PayableTarget payableTarget =newPayableTarget();
(addresssender, uint256value) =PayableTarget(
proxy._(address(payableTarget))
).funcA{value: 20ether}();

However, it's NOT possible to make plain ether transfers to a ForwardProxy/AuthForwardProxy:

payable(proxy).transfer(1 ether); // This will REVERT!

Alright, show me the code!

ForwardProxy usr1 =newForwardProxy();
ForwardProxy usr2 =newForwardProxy();
System system =newSystem(/* ... */);
system.authorize(address(usr1), 'role-A');
system.authorize(address(usr2), 'role-B');
// "Impersonate" a contract of type `System`System(
// Set the `system` contract as the target `to` and gets the reference to the proxy address.
usr1._(address(system))
)
// Call a method in the proxy which will be forwarded to the system
.authorizedMethodA();
// Do the same for `usr2`:System(usr2._(address(system))).authorizedMethodB();

The example above is roughly equivalent to the following using ethers.js:

constusr1=newethers.Wallet('<private key 1>');constusr2=newethers.Wallet('<private key 2>');constsystem=newethers.Contract('<address>','<abi>');consttx1=awaitsystem.authorize(address(usr1),'role-A');awaittx1.wait()consttx2=awaitsystem.authorize(address(usr2),'role-B');awaittx2.wait()system.connect(usr1);consttx3=awaitsystem.authorizedMethodA();awaittx3.wait();system.connect(usr2);consttx4=awaitsystem.authorizedMethodB();awaittx4.wait();

How to authorize addresses in AuthForwardProxy?

Each address allowed into AuthForwarProxy is a ward. Once an address receives a ward status, it can add or remove other wards, but it cannot modify the owner. The owner has root access to the contract.

To avoid naming clashes with the target contract, every public function on AuthForwardProxy that is not part of the ForwardProxyLike interface is appended of its own selector:

interfaceAuthForwardProxyLike {
///@notice Get the owner of the contract.///@dev The selector for `owner()` is `0x8da5cb5b` and so on...function owner_8da5cb5b() externalviewreturns (address);
///@notice Transfer the ownership of the contract.function transferOwnership_f2fde38b(addresswho) external;
///@notice Give `who` the ward role.function rely_65fae35e(addresswho) external;
///@notice Revokes the ward role for `who`.function deny_9c52a7f1(addresswho) external;
///@notice Gets the ward status of `who`.function wards_bf353dbb(addresswho) externalviewreturns (uint256);
}

After deploying the contract, the owner can call rely_65fae35e(address) to authorize a different address:

seth send "$AUTH_FORWARD_PROXY_ADDRESS""rely_65fae35e(address)""$WARD_ADDRESS"

About

`ForwardProxy` provides a fallback function that forwards all calls to another contract using the EVM `call` instruction.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Forward Proxy

Motivation

ForwardProxy is useful for permissioned smart contracts systems in environments where EOAs are not available (i.e.: tests written with ds-test) and there is a need to emulate different actors interacting with components of the system.
It can be thought of as a 1-out-of-∞ multisig to interact with other smart contracts.

AuthForwardProxy is an extension of ForwardPorxy that is useful for contracts whose permissioned methods should not be made completely permissionless by using ForwardProxy.
It can be thought of as a 1-out-of-N multisig to interact with other smart contracts.

How it works?

Both ForwardProxy and AuthForwardProxy provide a fallback function that forwards all calls to another contract using the EVM instruction call. The success and return data of the call will be returned back to the caller of the proxy.

Notice that this is different from OpenZeppelin's base Proxy contract, which uses delegatecall instead.

This largely alleviates the security issues that come with delegatecall, since the call to the target contract will be made on its own context, but this code has not been audited and I DO NOT recommend using it in production.

As it currently stands, this contract could be seen as a bare-bones permissionless 1-out-of-∞ multisig that allows interacting with smart contracts.

API

interfaceForwardProxyLike {
function __to() externalviewreturns (address);
function _() externalreturns (address);
}
  • __to(): returns the address of the target contract.
  • _(): updates the address of the target contract.

The methods have these peculiar names for 2 reasons:

  1. Keep it short, reducing the noise when reading the code.
  2. Minimize the chances of clashing names, which would prevent the proxy from working properly.

The setter method _() implements method chaining to make it more ergonomic:

Instead of:

proxy._(target);
Target(proxy).targetMethod();

You can write:

Target(proxy._(target)).targetMethod();

This is specially useful when the proxy needs to be used with multiple targets:

TargetA(proxy._(targetA)).targetAMethod();
TargetB(proxy._(targetB)).targetBMethod();

What about payable methods?

I'm glad you asked!

ForwardProxy/AuthForwardProxy also forward any ether sent through it to the target.

contractPayableTarget {
event A(addresswho, uint256wad);
function funcA() publicpayablereturns (address, uint256) {
emitA(msg.sender, msg.value);
return (msg.sender, msg.value);
}
receive() externalpayable {}
}
PayableTarget payableTarget =newPayableTarget();
(addresssender, uint256value) =PayableTarget(
proxy._(address(payableTarget))
).funcA{value: 20ether}();

However, it's NOT possible to make plain ether transfers to a ForwardProxy/AuthForwardProxy:

payable(proxy).transfer(1 ether); // This will REVERT!

Alright, show me the code!

ForwardProxy usr1 =newForwardProxy();
ForwardProxy usr2 =newForwardProxy();
System system =newSystem(/* ... */);
system.authorize(address(usr1), 'role-A');
system.authorize(address(usr2), 'role-B');
// "Impersonate" a contract of type `System`System(
// Set the `system` contract as the target `to` and gets the reference to the proxy address.
usr1._(address(system))
)
// Call a method in the proxy which will be forwarded to the system
.authorizedMethodA();
// Do the same for `usr2`:System(usr2._(address(system))).authorizedMethodB();

The example above is roughly equivalent to the following using ethers.js:

constusr1=newethers.Wallet('<private key 1>');constusr2=newethers.Wallet('<private key 2>');constsystem=newethers.Contract('<address>','<abi>');consttx1=awaitsystem.authorize(address(usr1),'role-A');awaittx1.wait()consttx2=awaitsystem.authorize(address(usr2),'role-B');awaittx2.wait()system.connect(usr1);consttx3=awaitsystem.authorizedMethodA();awaittx3.wait();system.connect(usr2);consttx4=awaitsystem.authorizedMethodB();awaittx4.wait();

How to authorize addresses in AuthForwardProxy?

Each address allowed into AuthForwarProxy is a ward. Once an address receives a ward status, it can add or remove other wards, but it cannot modify the owner. The owner has root access to the contract.

To avoid naming clashes with the target contract, every public function on AuthForwardProxy that is not part of the ForwardProxyLike interface is appended of its own selector:

interfaceAuthForwardProxyLike {
///@notice Get the owner of the contract.///@dev The selector for `owner()` is `0x8da5cb5b` and so on...function owner_8da5cb5b() externalviewreturns (address);
///@notice Transfer the ownership of the contract.function transferOwnership_f2fde38b(addresswho) external;
///@notice Give `who` the ward role.function rely_65fae35e(addresswho) external;
///@notice Revokes the ward role for `who`.function deny_9c52a7f1(addresswho) external;
///@notice Gets the ward status of `who`.function wards_bf353dbb(addresswho) externalviewreturns (uint256);
}

After deploying the contract, the owner can call rely_65fae35e(address) to authorize a different address:

seth send "$AUTH_FORWARD_PROXY_ADDRESS""rely_65fae35e(address)""$WARD_ADDRESS"

About

`ForwardProxy` provides a fallback function that forwards all calls to another contract using the EVM `call` instruction.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Forward Proxy

Motivation

ForwardProxy is useful for permissioned smart contracts systems in environments where EOAs are not available (i.e.: tests written with ds-test) and there is a need to emulate different actors interacting with components of the system.
It can be thought of as a 1-out-of-∞ multisig to interact with other smart contracts.

AuthForwardProxy is an extension of ForwardPorxy that is useful for contracts whose permissioned methods should not be made completely permissionless by using ForwardProxy.
It can be thought of as a 1-out-of-N multisig to interact with other smart contracts.

How it works?

Both ForwardProxy and AuthForwardProxy provide a fallback function that forwards all calls to another contract using the EVM instruction call. The success and return data of the call will be returned back to the caller of the proxy.

Notice that this is different from OpenZeppelin's base Proxy contract, which uses delegatecall instead.

This largely alleviates the security issues that come with delegatecall, since the call to the target contract will be made on its own context, but this code has not been audited and I DO NOT recommend using it in production.

As it currently stands, this contract could be seen as a bare-bones permissionless 1-out-of-∞ multisig that allows interacting with smart contracts.

API

interfaceForwardProxyLike {
function __to() externalviewreturns (address);
function _() externalreturns (address);
}
  • __to(): returns the address of the target contract.
  • _(): updates the address of the target contract.

The methods have these peculiar names for 2 reasons:

  1. Keep it short, reducing the noise when reading the code.
  2. Minimize the chances of clashing names, which would prevent the proxy from working properly.

The setter method _() implements method chaining to make it more ergonomic:

Instead of:

proxy._(target);
Target(proxy).targetMethod();

You can write:

Target(proxy._(target)).targetMethod();

This is specially useful when the proxy needs to be used with multiple targets:

TargetA(proxy._(targetA)).targetAMethod();
TargetB(proxy._(targetB)).targetBMethod();

What about payable methods?

I'm glad you asked!

ForwardProxy/AuthForwardProxy also forward any ether sent through it to the target.

contractPayableTarget {
event A(addresswho, uint256wad);
function funcA() publicpayablereturns (address, uint256) {
emitA(msg.sender, msg.value);
return (msg.sender, msg.value);
}
receive() externalpayable {}
}
PayableTarget payableTarget =newPayableTarget();
(addresssender, uint256value) =PayableTarget(
proxy._(address(payableTarget))
).funcA{value: 20ether}();

However, it's NOT possible to make plain ether transfers to a ForwardProxy/AuthForwardProxy:

payable(proxy).transfer(1 ether); // This will REVERT!

Alright, show me the code!

ForwardProxy usr1 =newForwardProxy();
ForwardProxy usr2 =newForwardProxy();
System system =newSystem(/* ... */);
system.authorize(address(usr1), 'role-A');
system.authorize(address(usr2), 'role-B');
// "Impersonate" a contract of type `System`System(
// Set the `system` contract as the target `to` and gets the reference to the proxy address.
usr1._(address(system))
)
// Call a method in the proxy which will be forwarded to the system
.authorizedMethodA();
// Do the same for `usr2`:System(usr2._(address(system))).authorizedMethodB();

The example above is roughly equivalent to the following using ethers.js:

constusr1=newethers.Wallet('<private key 1>');constusr2=newethers.Wallet('<private key 2>');constsystem=newethers.Contract('<address>','<abi>');consttx1=awaitsystem.authorize(address(usr1),'role-A');awaittx1.wait()consttx2=awaitsystem.authorize(address(usr2),'role-B');awaittx2.wait()system.connect(usr1);consttx3=awaitsystem.authorizedMethodA();awaittx3.wait();system.connect(usr2);consttx4=awaitsystem.authorizedMethodB();awaittx4.wait();

How to authorize addresses in AuthForwardProxy?

Each address allowed into AuthForwarProxy is a ward. Once an address receives a ward status, it can add or remove other wards, but it cannot modify the owner. The owner has root access to the contract.

To avoid naming clashes with the target contract, every public function on AuthForwardProxy that is not part of the ForwardProxyLike interface is appended of its own selector:

interfaceAuthForwardProxyLike {
///@notice Get the owner of the contract.///@dev The selector for `owner()` is `0x8da5cb5b` and so on...function owner_8da5cb5b() externalviewreturns (address);
///@notice Transfer the ownership of the contract.function transferOwnership_f2fde38b(addresswho) external;
///@notice Give `who` the ward role.function rely_65fae35e(addresswho) external;
///@notice Revokes the ward role for `who`.function deny_9c52a7f1(addresswho) external;
///@notice Gets the ward status of `who`.function wards_bf353dbb(addresswho) externalviewreturns (uint256);
}

After deploying the contract, the owner can call rely_65fae35e(address) to authorize a different address:

seth send "$AUTH_FORWARD_PROXY_ADDRESS""rely_65fae35e(address)""$WARD_ADDRESS"

About

`ForwardProxy` provides a fallback function that forwards all calls to another contract using the EVM `call` instruction.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Forward Proxy

Motivation

ForwardProxy is useful for permissioned smart contracts systems in environments where EOAs are not available (i.e.: tests written with ds-test) and there is a need to emulate different actors interacting with components of the system.
It can be thought of as a 1-out-of-∞ multisig to interact with other smart contracts.

AuthForwardProxy is an extension of ForwardPorxy that is useful for contracts whose permissioned methods should not be made completely permissionless by using ForwardProxy.
It can be thought of as a 1-out-of-N multisig to interact with other smart contracts.

How it works?

Both ForwardProxy and AuthForwardProxy provide a fallback function that forwards all calls to another contract using the EVM instruction call. The success and return data of the call will be returned back to the caller of the proxy.

Notice that this is different from OpenZeppelin's base Proxy contract, which uses delegatecall instead.

This largely alleviates the security issues that come with delegatecall, since the call to the target contract will be made on its own context, but this code has not been audited and I DO NOT recommend using it in production.

As it currently stands, this contract could be seen as a bare-bones permissionless 1-out-of-∞ multisig that allows interacting with smart contracts.

API

interfaceForwardProxyLike {
function __to() externalviewreturns (address);
function _() externalreturns (address);
}
  • __to(): returns the address of the target contract.
  • _(): updates the address of the target contract.

The methods have these peculiar names for 2 reasons:

  1. Keep it short, reducing the noise when reading the code.
  2. Minimize the chances of clashing names, which would prevent the proxy from working properly.

The setter method _() implements method chaining to make it more ergonomic:

Instead of:

proxy._(target);
Target(proxy).targetMethod();

You can write:

Target(proxy._(target)).targetMethod();

This is specially useful when the proxy needs to be used with multiple targets:

TargetA(proxy._(targetA)).targetAMethod();
TargetB(proxy._(targetB)).targetBMethod();

What about payable methods?

I'm glad you asked!

ForwardProxy/AuthForwardProxy also forward any ether sent through it to the target.

contractPayableTarget {
event A(addresswho, uint256wad);
function funcA() publicpayablereturns (address, uint256) {
emitA(msg.sender, msg.value);
return (msg.sender, msg.value);
}
receive() externalpayable {}
}
PayableTarget payableTarget =newPayableTarget();
(addresssender, uint256value) =PayableTarget(
proxy._(address(payableTarget))
).funcA{value: 20ether}();

However, it's NOT possible to make plain ether transfers to a ForwardProxy/AuthForwardProxy:

payable(proxy).transfer(1 ether); // This will REVERT!

Alright, show me the code!

ForwardProxy usr1 =newForwardProxy();
ForwardProxy usr2 =newForwardProxy();
System system =newSystem(/* ... */);
system.authorize(address(usr1), 'role-A');
system.authorize(address(usr2), 'role-B');
// "Impersonate" a contract of type `System`System(
// Set the `system` contract as the target `to` and gets the reference to the proxy address.
usr1._(address(system))
)
// Call a method in the proxy which will be forwarded to the system
.authorizedMethodA();
// Do the same for `usr2`:System(usr2._(address(system))).authorizedMethodB();

The example above is roughly equivalent to the following using ethers.js:

constusr1=newethers.Wallet('<private key 1>');constusr2=newethers.Wallet('<private key 2>');constsystem=newethers.Contract('<address>','<abi>');consttx1=awaitsystem.authorize(address(usr1),'role-A');awaittx1.wait()consttx2=awaitsystem.authorize(address(usr2),'role-B');awaittx2.wait()system.connect(usr1);consttx3=awaitsystem.authorizedMethodA();awaittx3.wait();system.connect(usr2);consttx4=awaitsystem.authorizedMethodB();awaittx4.wait();

How to authorize addresses in AuthForwardProxy?

Each address allowed into AuthForwarProxy is a ward. Once an address receives a ward status, it can add or remove other wards, but it cannot modify the owner. The owner has root access to the contract.

To avoid naming clashes with the target contract, every public function on AuthForwardProxy that is not part of the ForwardProxyLike interface is appended of its own selector:

interfaceAuthForwardProxyLike {
///@notice Get the owner of the contract.///@dev The selector for `owner()` is `0x8da5cb5b` and so on...function owner_8da5cb5b() externalviewreturns (address);
///@notice Transfer the ownership of the contract.function transferOwnership_f2fde38b(addresswho) external;
///@notice Give `who` the ward role.function rely_65fae35e(addresswho) external;
///@notice Revokes the ward role for `who`.function deny_9c52a7f1(addresswho) external;
///@notice Gets the ward status of `who`.function wards_bf353dbb(addresswho) externalviewreturns (uint256);
}

After deploying the contract, the owner can call rely_65fae35e(address) to authorize a different address:

seth send "$AUTH_FORWARD_PROXY_ADDRESS""rely_65fae35e(address)""$WARD_ADDRESS"

About

`ForwardProxy` provides a fallback function that forwards all calls to another contract using the EVM `call` instruction.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Forward Proxy

Motivation

ForwardProxy is useful for permissioned smart contracts systems in environments where EOAs are not available (i.e.: tests written with ds-test) and there is a need to emulate different actors interacting with components of the system.
It can be thought of as a 1-out-of-∞ multisig to interact with other smart contracts.

AuthForwardProxy is an extension of ForwardPorxy that is useful for contracts whose permissioned methods should not be made completely permissionless by using ForwardProxy.
It can be thought of as a 1-out-of-N multisig to interact with other smart contracts.

How it works?

Both ForwardProxy and AuthForwardProxy provide a fallback function that forwards all calls to another contract using the EVM instruction call. The success and return data of the call will be returned back to the caller of the proxy.

Notice that this is different from OpenZeppelin's base Proxy contract, which uses delegatecall instead.

This largely alleviates the security issues that come with delegatecall, since the call to the target contract will be made on its own context, but this code has not been audited and I DO NOT recommend using it in production.

As it currently stands, this contract could be seen as a bare-bones permissionless 1-out-of-∞ multisig that allows interacting with smart contracts.

API

interfaceForwardProxyLike {
function __to() externalviewreturns (address);
function _() externalreturns (address);
}
  • __to(): returns the address of the target contract.
  • _(): updates the address of the target contract.

The methods have these peculiar names for 2 reasons:

  1. Keep it short, reducing the noise when reading the code.
  2. Minimize the chances of clashing names, which would prevent the proxy from working properly.

The setter method _() implements method chaining to make it more ergonomic:

Instead of:

proxy._(target);
Target(proxy).targetMethod();

You can write:

Target(proxy._(target)).targetMethod();

This is specially useful when the proxy needs to be used with multiple targets:

TargetA(proxy._(targetA)).targetAMethod();
TargetB(proxy._(targetB)).targetBMethod();

What about payable methods?

I'm glad you asked!

ForwardProxy/AuthForwardProxy also forward any ether sent through it to the target.

contractPayableTarget {
event A(addresswho, uint256wad);
function funcA() publicpayablereturns (address, uint256) {
emitA(msg.sender, msg.value);
return (msg.sender, msg.value);
}
receive() externalpayable {}
}
PayableTarget payableTarget =newPayableTarget();
(addresssender, uint256value) =PayableTarget(
proxy._(address(payableTarget))
).funcA{value: 20ether}();

However, it's NOT possible to make plain ether transfers to a ForwardProxy/AuthForwardProxy:

payable(proxy).transfer(1 ether); // This will REVERT!

Alright, show me the code!

ForwardProxy usr1 =newForwardProxy();
ForwardProxy usr2 =newForwardProxy();
System system =newSystem(/* ... */);
system.authorize(address(usr1), 'role-A');
system.authorize(address(usr2), 'role-B');
// "Impersonate" a contract of type `System`System(
// Set the `system` contract as the target `to` and gets the reference to the proxy address.
usr1._(address(system))
)
// Call a method in the proxy which will be forwarded to the system
.authorizedMethodA();
// Do the same for `usr2`:System(usr2._(address(system))).authorizedMethodB();

The example above is roughly equivalent to the following using ethers.js:

constusr1=newethers.Wallet('<private key 1>');constusr2=newethers.Wallet('<private key 2>');constsystem=newethers.Contract('<address>','<abi>');consttx1=awaitsystem.authorize(address(usr1),'role-A');awaittx1.wait()consttx2=awaitsystem.authorize(address(usr2),'role-B');awaittx2.wait()system.connect(usr1);consttx3=awaitsystem.authorizedMethodA();awaittx3.wait();system.connect(usr2);consttx4=awaitsystem.authorizedMethodB();awaittx4.wait();

How to authorize addresses in AuthForwardProxy?

Each address allowed into AuthForwarProxy is a ward. Once an address receives a ward status, it can add or remove other wards, but it cannot modify the owner. The owner has root access to the contract.

To avoid naming clashes with the target contract, every public function on AuthForwardProxy that is not part of the ForwardProxyLike interface is appended of its own selector:

interfaceAuthForwardProxyLike {
///@notice Get the owner of the contract.///@dev The selector for `owner()` is `0x8da5cb5b` and so on...function owner_8da5cb5b() externalviewreturns (address);
///@notice Transfer the ownership of the contract.function transferOwnership_f2fde38b(addresswho) external;
///@notice Give `who` the ward role.function rely_65fae35e(addresswho) external;
///@notice Revokes the ward role for `who`.function deny_9c52a7f1(addresswho) external;
///@notice Gets the ward status of `who`.function wards_bf353dbb(addresswho) externalviewreturns (uint256);
}

After deploying the contract, the owner can call rely_65fae35e(address) to authorize a different address:

seth send "$AUTH_FORWARD_PROXY_ADDRESS""rely_65fae35e(address)""$WARD_ADDRESS"

About

`ForwardProxy` provides a fallback function that forwards all calls to another contract using the EVM `call` instruction.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Forward Proxy

Motivation

ForwardProxy is useful for permissioned smart contracts systems in environments where EOAs are not available (i.e.: tests written with ds-test) and there is a need to emulate different actors interacting with components of the system.
It can be thought of as a 1-out-of-∞ multisig to interact with other smart contracts.

AuthForwardProxy is an extension of ForwardPorxy that is useful for contracts whose permissioned methods should not be made completely permissionless by using ForwardProxy.
It can be thought of as a 1-out-of-N multisig to interact with other smart contracts.

How it works?

Both ForwardProxy and AuthForwardProxy provide a fallback function that forwards all calls to another contract using the EVM instruction call. The success and return data of the call will be returned back to the caller of the proxy.

Notice that this is different from OpenZeppelin's base Proxy contract, which uses delegatecall instead.

This largely alleviates the security issues that come with delegatecall, since the call to the target contract will be made on its own context, but this code has not been audited and I DO NOT recommend using it in production.

As it currently stands, this contract could be seen as a bare-bones permissionless 1-out-of-∞ multisig that allows interacting with smart contracts.

API

interfaceForwardProxyLike {
function __to() externalviewreturns (address);
function _() externalreturns (address);
}
  • __to(): returns the address of the target contract.
  • _(): updates the address of the target contract.

The methods have these peculiar names for 2 reasons:

  1. Keep it short, reducing the noise when reading the code.
  2. Minimize the chances of clashing names, which would prevent the proxy from working properly.

The setter method _() implements method chaining to make it more ergonomic:

Instead of:

proxy._(target);
Target(proxy).targetMethod();

You can write:

Target(proxy._(target)).targetMethod();

This is specially useful when the proxy needs to be used with multiple targets:

TargetA(proxy._(targetA)).targetAMethod();
TargetB(proxy._(targetB)).targetBMethod();

What about payable methods?

I'm glad you asked!

ForwardProxy/AuthForwardProxy also forward any ether sent through it to the target.

contractPayableTarget {
event A(addresswho, uint256wad);
function funcA() publicpayablereturns (address, uint256) {
emitA(msg.sender, msg.value);
return (msg.sender, msg.value);
}
receive() externalpayable {}
}
PayableTarget payableTarget =newPayableTarget();
(addresssender, uint256value) =PayableTarget(
proxy._(address(payableTarget))
).funcA{value: 20ether}();

However, it's NOT possible to make plain ether transfers to a ForwardProxy/AuthForwardProxy:

payable(proxy).transfer(1 ether); // This will REVERT!

Alright, show me the code!

ForwardProxy usr1 =newForwardProxy();
ForwardProxy usr2 =newForwardProxy();
System system =newSystem(/* ... */);
system.authorize(address(usr1), 'role-A');
system.authorize(address(usr2), 'role-B');
// "Impersonate" a contract of type `System`System(
// Set the `system` contract as the target `to` and gets the reference to the proxy address.
usr1._(address(system))
)
// Call a method in the proxy which will be forwarded to the system
.authorizedMethodA();
// Do the same for `usr2`:System(usr2._(address(system))).authorizedMethodB();

The example above is roughly equivalent to the following using ethers.js:

constusr1=newethers.Wallet('<private key 1>');constusr2=newethers.Wallet('<private key 2>');constsystem=newethers.Contract('<address>','<abi>');consttx1=awaitsystem.authorize(address(usr1),'role-A');awaittx1.wait()consttx2=awaitsystem.authorize(address(usr2),'role-B');awaittx2.wait()system.connect(usr1);consttx3=awaitsystem.authorizedMethodA();awaittx3.wait();system.connect(usr2);consttx4=awaitsystem.authorizedMethodB();awaittx4.wait();

How to authorize addresses in AuthForwardProxy?

Each address allowed into AuthForwarProxy is a ward. Once an address receives a ward status, it can add or remove other wards, but it cannot modify the owner. The owner has root access to the contract.

To avoid naming clashes with the target contract, every public function on AuthForwardProxy that is not part of the ForwardProxyLike interface is appended of its own selector:

interfaceAuthForwardProxyLike {
///@notice Get the owner of the contract.///@dev The selector for `owner()` is `0x8da5cb5b` and so on...function owner_8da5cb5b() externalviewreturns (address);
///@notice Transfer the ownership of the contract.function transferOwnership_f2fde38b(addresswho) external;
///@notice Give `who` the ward role.function rely_65fae35e(addresswho) external;
///@notice Revokes the ward role for `who`.function deny_9c52a7f1(addresswho) external;
///@notice Gets the ward status of `who`.function wards_bf353dbb(addresswho) externalviewreturns (uint256);
}

After deploying the contract, the owner can call rely_65fae35e(address) to authorize a different address:

seth send "$AUTH_FORWARD_PROXY_ADDRESS""rely_65fae35e(address)""$WARD_ADDRESS"

About

`ForwardProxy` provides a fallback function that forwards all calls to another contract using the EVM `call` instruction.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages