Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xC63e9279410d37C0A25D094e26Cddbb73aEd7d95
Balance 0 ETH
Nonce 152
Code Size 9617 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

9617 bytes
0x60806040523480156200001157600080fd5b5060043610620001455760003560e01c80639d1bd15911620000bb578063b9678403116200007a578063b96784031462000365578063bf3a5c02146200037c578063fa557e9314620003a8578063fb4a4d0814620003bf578063ffa1ad7414620003d657600080fd5b80639d1bd15914620002a8578063aa4b826a14620002bf578063ae22c57d14620002d6578063b31d1b9914620002ed578063b7fba4d3146200033657600080fd5b806361be4859116200010857806361be485914620002025780636383afb2146200024657806366b0182d146200026c57806374912cd21462000287578063775c300c146200029e57600080fd5b8063092af813146200014a5780631ddef5b914620001795780632971038814620001905780634bddd93a14620001d25780635cabcdf714620001eb575b600080fd5b620001616200015b3660046200138a565b6200040a565b604051620001709190620013e5565b60405180910390f35b620001616200018a36600462001410565b620004a2565b620001c1620001a13660046200144e565b6001600160a01b0390811660009081526007602052604090205416151590565b604051901515815260200162000170565b620001e9620001e33660046200144e565b6200054c565b005b620001c1620001fc36600462001475565b62000762565b620001616200021336600462001410565b6001600160a01b0391821660009081526005602090815260408083206001600160e01b0319909416835292905220541690565b6200025d62000257366004620014c7565b6200080b565b604051620001709190620014fa565b620002766200093f565b60405162000170939291906200159e565b62000161620002983660046200144e565b620009ef565b6200016162000a59565b62000161620002b9366004620015d5565b62000abf565b620001e9620002d036600462001645565b62000b5b565b62000161620002e73660046200144e565b62000c1f565b620001c1620002fe36600462001475565b6001600160a01b0392831660009081526004602090815260408083209486168352938152838220929094168152925290205460ff1690565b62000161620003473660046200144e565b6001600160a01b039081166000908152600660205260409020541690565b620001e9620003763660046200144e565b62000cf2565b620001616200038d3660046200144e565b6007602052600090815260409020546001600160a01b031681565b6200025d620003b9366004620014c7565b62000d3b565b62000161620003d03660046200144e565b62000dc1565b620003fb60405180604001604052806005815260200164342e302e3160d81b81525081565b60405162000170919062001690565b336000818152600660205260408120549091906001600160a01b031680156200045557818160405163bf0b215b60e01b81526004016200044c929190620016a5565b60405180910390fd5b62000498338787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062000e3492505050565b9695505050505050565b600060056000846001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620004e7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200050d9190620016bf565b6001600160a01b039081168252602080830193909352604091820160009081206001600160e01b03199096168152949092529092205490911692915050565b336000908152600660205260409020546001600160a01b03166200058757336040516333685ad760e01b81526004016200044c9190620013e5565b3360008181526003602090815260408083206001600160a01b03861684528252808320805482518185028101850190935280835291929091908301828280156200061e57602002820191906000526020600020906000905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411620005df5790505b50505050509050600081519050806000036200065157836040516338d4b05760e01b81526004016200044c9190620013e5565b60005b81811015620006ca576001600160a01b038416600090815260056020526040812084519091908590849081106200068f576200068f620016df565b6020908102919091018101516001600160e01b031916825281019190915260400160002080546001600160a01b031916905560010162000654565b506001600160a01b0380841660009081526003602090815260408083209388168352929052908120620006fd91620011ea565b6001600160a01b0383811660008181526006602052604090819020549051838816939190911691907f0971095f3fa0f917fd0ad98319d7cdb8e837d8c98d5e47fb2700e8b68ac961c99062000754908790620014fa565b60405180910390a450505050565b600060046000856001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620007a7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620007cd9190620016bf565b6001600160a01b039081168252602080830193909352604091820160009081209682168152958352818620941685529290525090205460ff16919050565b606060036000846001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000850573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008769190620016bf565b6001600160a01b03166001600160a01b031681526020019081526020016000206000836001600160a01b03166001600160a01b031681526020019081526020016000208054806020026020016040519081016040528092919081815260200182805480156200093257602002820191906000526020600020906000905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411620008f35790505b5050505050905092915050565b60008054600154600280546001600160a01b039384169492909316926200096690620016f5565b80601f01602080910402602001604051908101604052809291908181526020018280546200099490620016f5565b8015620009e55780601f10620009b957610100808354040283529160200191620009e5565b820191906000526020600020905b815481529060010190602001808311620009c757829003601f168201915b5050505050905083565b6001600160a01b038082166000908152600660205260408120549091839116801562000a3457818160405163bf0b215b60e01b81526004016200044c929190620016a5565b62000a518460006040518060200160405280600081525062000e34565b949350505050565b336000818152600660205260408120549091906001600160a01b0316801562000a9b57818160405163bf0b215b60e01b81526004016200044c929190620016a5565b62000ab83360006040518060200160405280600081525062000e34565b9250505090565b336000818152600660205260408120549091906001600160a01b0316801562000b0157818160405163bf0b215b60e01b81526004016200044c929190620016a5565b62000b44338888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062000e3492505050565b925062000b518462000fab565b5050949350505050565b336000908152600660205260409020546001600160a01b031662000b9657336040516333685ad760e01b81526004016200044c9190620013e5565b3360008181526004602090815260408083206001600160a01b03888116808652918452828520888216808752908552838620805460ff1916891515908117909155878752600686529584902054845191825294810195909552909392169184917f4f2bd80fb4928b06abcd76e3b26209a615f0612f98dc4a8b176934b1a3899333910162000754565b6000808260405160200162000c35919062001731565b60405160208183030381529060405262000c4f9062001749565b905060006040518060200162000c659062001211565b601f1982820381018352601f90910116604081905262000c8991906020016200176e565b60408051808303601f1901815282825280516020918201206001600160f81b0319828501523060601b6001600160601b03191660218501526035840195909552605580840195909552815180840390950185526075909201905282519201919091209392505050565b336000908152600660205260409020546001600160a01b031662000d2d57336040516333685ad760e01b81526004016200044c9190620013e5565b62000d388162000fab565b50565b6001600160a01b03808316600090815260036020908152604080832093851683529281529082902080548351818402810184019094528084526060939283018282801562000932576000918252602091829020805460e01b6001600160e01b0319168452908202830192909160049101808411620008f357509498975050505050505050565b336000818152600660205260408120549091906001600160a01b0316801562000e0357818160405163bf0b215b60e01b81526004016200044c929190620016a5565b62000e203360006040518060200160405280600081525062000e34565b925062000e2d8462000fab565b5050919050565b6000808460405160200162000e4a919062001731565b60405160208183030381529060405262000e649062001749565b604080516060810182526001600160a01b0380891680835290881660208301819052928201879052600080546001600160a01b03199081169092178155600180549092169093179055919250600262000ebe8682620017f5565b509050508060405162000ed19062001211565b8190604051809103906000f590508015801562000ef2573d6000803e3d6000fd5b50600080546001600160a01b031990811682556001805490911690559092508062000f1f6002826200121f565b50506001600160a01b03808616600081815260066020908152604080832080549588166001600160a01b03199687168117909155835260079091529081902080549093168217909255905133907f2d8895d948115783fa362a57339c4c179365fafeafdd7dca66364ae296f50b759062000f9b908690620013e5565b60405180910390a3509392505050565b6000816001600160a01b0316636aeb45946040518163ffffffff1660e01b81526004016000604051808303816000875af115801562000fee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620010189190810190620018d4565b805190915060008190036200104457826040516362d3093d60e11b81526004016200044c9190620013e5565b3360005b828110156200115a576000848281518110620010685762001068620016df565b6020908102919091018101516001600160a01b0385811660009081526005845260408082206001600160e01b031985168352909452929092205490925016156200110a576001600160a01b0383811660009081526005602090815260408083206001600160e01b031986168085529252918290205491516361a2116b60e11b81529183166004830152918816602482015260448101919091526064016200044c565b6001600160a01b0383811660009081526005602090815260408083206001600160e01b03199590951683529390529190912080546001600160a01b03191691871691909117905560010162001048565b506001600160a01b0380821660009081526003602090815260408083209388168352928152919020845162001192928601906200125e565b506001600160a01b0381811660008181526006602052604090819020549051838816939190911691907f71b3c95c0b8611d2f0f9c4e492ebbcf20d034943bccac6ef1a71ae90e0f243fa9062000754908890620014fa565b50805460008255600701600890049060005260206000209081019062000d38919062001311565b610bb480620019a883390190565b5080546200122d90620016f5565b6000825580601f106200123e575050565b601f01602090049060005260206000209081019062000d38919062001311565b82805482825590600052602060002090600701600890048101928215620012ff5791602002820160005b83821115620012cb57835183826101000a81548163ffffffff021916908360e01c0217905550926020019260040160208160030104928301926001030262001288565b8015620012fd5782816101000a81549063ffffffff0219169055600401602081600301049283019260010302620012cb565b505b506200130d92915062001311565b5090565b5b808211156200130d576000815560010162001312565b6001600160a01b038116811462000d3857600080fd5b60008083601f8401126200135157600080fd5b50813567ffffffffffffffff8111156200136a57600080fd5b6020830191508360208285010111156200138357600080fd5b9250929050565b600080600060408486031215620013a057600080fd5b8335620013ad8162001328565b9250602084013567ffffffffffffffff811115620013ca57600080fd5b620013d8868287016200133e565b9497909650939450505050565b6001600160a01b0391909116815260200190565b6001600160e01b03198116811462000d3857600080fd5b600080604083850312156200142457600080fd5b8235620014318162001328565b915060208301356200144381620013f9565b809150509250929050565b6000602082840312156200146157600080fd5b81356200146e8162001328565b9392505050565b6000806000606084860312156200148b57600080fd5b8335620014988162001328565b92506020840135620014aa8162001328565b91506040840135620014bc8162001328565b809150509250925092565b60008060408385031215620014db57600080fd5b8235620014e88162001328565b91506020830135620014438162001328565b6020808252825182820181905260009190848201906040850190845b818110156200153e5783516001600160e01b0319168352928401929184019160010162001516565b50909695505050505050565b60005b83811015620015675781810151838201526020016200154d565b50506000910152565b600081518084526200158a8160208601602086016200154a565b601f01601f19169290920160200192915050565b6001600160a01b03848116825283166020820152606060408201819052600090620015cc9083018462001570565b95945050505050565b60008060008060608587031215620015ec57600080fd5b8435620015f98162001328565b9350602085013567ffffffffffffffff8111156200161657600080fd5b62001624878288016200133e565b90945092505060408501356200163a8162001328565b939692955090935050565b6000806000606084860312156200165b57600080fd5b8335620016688162001328565b925060208401356200167a8162001328565b915060408401358015158114620014bc57600080fd5b6020815260006200146e602083018462001570565b6001600160a01b0392831681529116602082015260400190565b600060208284031215620016d257600080fd5b81516200146e8162001328565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200170a57607f821691505b6020821081036200172b57634e487b7160e01b600052602260045260246000fd5b50919050565b60609190911b6001600160601b031916815260140190565b805160208083015191908110156200172b5760001960209190910360031b1b16919050565b60008251620017828184602087016200154a565b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b601f821115620017f057600081815260208120601f850160051c81016020861015620017cb5750805b601f850160051c820191505b81811015620017ec57828155600101620017d7565b5050505b505050565b815167ffffffffffffffff8111156200181257620018126200178c565b6200182a81620018238454620016f5565b84620017a2565b602080601f831160018114620018625760008415620018495750858301515b600019600386901b1c1916600185901b178555620017ec565b600085815260208120601f198616915b82811015620018935788860151825594840194600190910190840162001872565b5085821015620018b25787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8051620018cf81620013f9565b919050565b60006020808385031215620018e857600080fd5b825167ffffffffffffffff808211156200190157600080fd5b818501915085601f8301126200191657600080fd5b8151818111156200192b576200192b6200178c565b8060051b604051601f19603f830116810181811085821117156200195357620019536200178c565b6040529182528482019250838101850191888311156200197257600080fd5b938501935b828510156200199b576200198b85620018c2565b8452938501939285019262001977565b9897505050505050505056fe60c06040523480156200001157600080fd5b503360a0819052604080516366b0182d60e01b81529051600092839283926366b0182d9160048082019286929091908290030181865afa1580156200005a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000084919081019062000232565b6001600160a01b038084166080529295509093509150821615620000b057620000ae8282620000b9565b505b50505062000390565b6060826001600160a01b03163b600003620000f657604051636d17e5ef60e11b81526001600160a01b038416600482015260240160405180910390fd5b6000836001600160a01b03168360405162000112919062000312565b600060405180830381855af49150503d80600081146200014f576040519150601f19603f3d011682016040523d82523d6000602084013e62000154565b606091505b508093508192505050836001600160a01b03167fb24ebe141c5f2a744b103bea65fce6c40e0dc65d7341d092c09b160f4044799084846040516200019a9291906200035e565b60405180910390a280620001d257815115620001b95781518060208401fd5b60405163061a160d60e41b815260040160405180910390fd5b5092915050565b80516001600160a01b0381168114620001f157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620002295781810151838201526020016200020f565b50506000910152565b6000806000606084860312156200024857600080fd5b6200025384620001d9565b92506200026360208501620001d9565b60408501519092506001600160401b03808211156200028157600080fd5b818601915086601f8301126200029657600080fd5b815181811115620002ab57620002ab620001f6565b604051601f8201601f19908116603f01168101908382118183101715620002d657620002d6620001f6565b81604052828152896020848701011115620002f057600080fd5b620003038360208301602088016200020c565b80955050505050509250925092565b60008251620003268184602087016200020c565b9190910192915050565b600081518084526200034a8160208601602086016200020c565b601f01601f19169290920160200192915050565b60408152600062000373604083018562000330565b828103602084015262000387818562000330565b95945050505050565b60805160a0516107cf620003e5600039600081816099015281816102970152610346015260008181605601528181610131015281816102d8015281816102fe0152818161037301526103e901526107cf6000f3fe6080604052600436106100385760003560e01c80631cff79cd1461025c5780637b103999146102855780638da5cb5b146102c65761003f565b3661003f57005b6040516361be485960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152600080356001600160e01b031916602484015291369160609184917f000000000000000000000000000000000000000000000000000000000000000016906361be485990604401602060405180830381865afa1580156100e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101049190610592565b90506001600160a01b03811661017557604051638848730f60e01b81523360048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248201526001600160e01b03196000351660448201526064015b60405180910390fd5b6000816001600160a01b031685856040516101919291906105b6565b600060405180830381855af49150503d80600081146101cc576040519150601f19603f3d011682016040523d82523d6000602084013e6101d1565b606091505b508094508192505050816001600160a01b03167fc4dabe0d7ef7462e2218f2c398c21ef217803e1c46f5cf802d1a5d1d9b503f2f86868660405161021793929190610616565b60405180910390a28061024f578251156102345782518084602001fd5b8160405163023c045d60e21b815260040161016c919061065e565b5050915050805190602001f35b61026f61026a366004610672565b6102fa565b60405161027c91906106f7565b60405180910390f35b34801561029157600080fd5b506102b97f000000000000000000000000000000000000000000000000000000000000000081565b60405161027c919061065e565b3480156102d257600080fd5b506102b97f000000000000000000000000000000000000000000000000000000000000000081565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146104285760405163b31d1b9960e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b31d1b999061039f907f00000000000000000000000000000000000000000000000000000000000000009033908a9060040161070a565b602060405180830381865afa1580156103bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e0919061072d565b905080610426577f000000000000000000000000000000000000000000000000000000000000000033866040516355d1750960e01b815260040161016c9392919061070a565b505b6104688484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047092505050565b949350505050565b6060826001600160a01b03163b60000361049f5782604051636d17e5ef60e11b815260040161016c919061065e565b6000836001600160a01b0316836040516104b9919061074f565b600060405180830381855af49150503d80600081146104f4576040519150601f19603f3d011682016040523d82523d6000602084013e6104f9565b606091505b508093508192505050836001600160a01b03167fb24ebe141c5f2a744b103bea65fce6c40e0dc65d7341d092c09b160f40447990848460405161053d92919061076b565b60405180910390a2806105735781511561055a5781518060208401fd5b60405163061a160d60e41b815260040160405180910390fd5b5092915050565b6001600160a01b038116811461058f57600080fd5b50565b6000602082840312156105a457600080fd5b81516105af8161057a565b9392505050565b8183823760009101908152919050565b60005b838110156105e15781810151838201526020016105c9565b50506000910152565b600081518084526106028160208601602086016105c6565b601f01601f19169290920160200192915050565b60408152826040820152828460608301376000606084830101526000601f19601f8501168201606083820301602084015261065460608201856105ea565b9695505050505050565b6001600160a01b0391909116815260200190565b60008060006040848603121561068757600080fd5b83356106928161057a565b9250602084013567ffffffffffffffff808211156106af57600080fd5b818601915086601f8301126106c357600080fd5b8135818111156106d257600080fd5b8760208285010111156106e457600080fd5b6020830194508093505050509250925092565b6020815260006105af60208301846105ea565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561073f57600080fd5b815180151581146105af57600080fd5b600082516107618184602087016105c6565b9190910192915050565b60408152600061077e60408301856105ea565b828103602084015261079081856105ea565b9594505050505056fea2646970667358221220a356d59a9849a7e1191e23f26bb1fd5ea445de34e1890e125a571ad90181c51b64736f6c63430008130033a26469706673582212207403e11ffc740beed2b6483791f47bbb98db17581dc730ade75c01efe889642f64736f6c63430008130033

Verified Source Code Partial Match

Compiler: v0.8.19+commit.7dd6d404 EVM: paris Optimization: Yes (100 runs)
PRBProxyRegistry.sol 290 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.18;

import {IPRBProxy} from "prb-proxy/interfaces/IPRBProxy.sol";
import {IPRBProxyPlugin} from "prb-proxy/interfaces/IPRBProxyPlugin.sol";
import {IPRBProxyRegistry} from "./interfaces/IPRBProxyRegistry.sol";
import {PRBProxy} from "prb-proxy/PRBProxy.sol";

/*

██████╗ ██████╗ ██████╗ ██████╗ ██████╗  ██████╗ ██╗  ██╗██╗   ██╗
██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔═══██╗╚██╗██╔╝╚██╗ ██╔╝
██████╔╝██████╔╝██████╔╝██████╔╝██████╔╝██║   ██║ ╚███╔╝  ╚████╔╝
██╔═══╝ ██╔══██╗██╔══██╗██╔═══╝ ██╔══██╗██║   ██║ ██╔██╗   ╚██╔╝
██║     ██║  ██║██████╔╝██║     ██║  ██║╚██████╔╝██╔╝ ██╗   ██║
╚═╝     ╚═╝  ╚═╝╚═════╝ ╚═╝     ╚═╝  ╚═╝ ╚═════╝ ╚═╝  ╚═╝   ╚═╝

██████╗ ███████╗ ██████╗ ██╗███████╗████████╗██████╗ ██╗   ██╗
██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔══██╗╚██╗ ██╔╝
██████╔╝█████╗  ██║  ███╗██║███████╗   ██║   ██████╔╝ ╚████╔╝
██╔══██╗██╔══╝  ██║   ██║██║╚════██║   ██║   ██╔══██╗  ╚██╔╝
██║  ██║███████╗╚██████╔╝██║███████║   ██║   ██║  ██║   ██║
╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝   ╚═╝

*/

/// @title PRBProxyRegistry
/// @dev See the documentation in {IPRBProxyRegistry}.
contract PRBProxyRegistry is IPRBProxyRegistry {
    /*//////////////////////////////////////////////////////////////////////////
                                     CONSTANTS
    //////////////////////////////////////////////////////////////////////////*/

    /// @inheritdoc IPRBProxyRegistry
    string public constant override VERSION = "4.0.1";

    /*//////////////////////////////////////////////////////////////////////////
                                USER-FACING STORAGE
    //////////////////////////////////////////////////////////////////////////*/

    /// @inheritdoc IPRBProxyRegistry
    ConstructorParams public override constructorParams;

    /*//////////////////////////////////////////////////////////////////////////
                                  INTERNAL STORAGE
    //////////////////////////////////////////////////////////////////////////*/

    mapping(address owner => mapping(IPRBProxyPlugin plugin => bytes4[] methods)) internal _methods;

    mapping(address owner => mapping(address envoy => mapping(address target => bool permission)))
        internal _permissions;

    mapping(address owner => mapping(bytes4 method => IPRBProxyPlugin plugin)) internal _plugins;

    mapping(address owner => IPRBProxy proxy) internal _proxies;

    mapping(IPRBProxy prbProxy => address owner) public _owners;

    /*//////////////////////////////////////////////////////////////////////////
                                     MODIFIERS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Checks that the caller has a proxy.
    modifier onlyCallerWithProxy() {
        if (address(_proxies[msg.sender]) == address(0)) {
            revert PRBProxyRegistry_UserDoesNotHaveProxy(msg.sender);
        }
        _;
    }

    /// @notice Check that the user does not have a proxy.
    modifier onlyNonProxyOwner(address user) {
        IPRBProxy proxy = _proxies[user];
        if (address(proxy) != address(0)) {
            revert PRBProxyRegistry_UserHasProxy(user, proxy);
        }
        _;
    }

    /*//////////////////////////////////////////////////////////////////////////
                           USER-FACING CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @inheritdoc IPRBProxyRegistry
    function getMethodsByOwner(address owner, IPRBProxyPlugin plugin) external view returns (bytes4[] memory methods) {
        methods = _methods[owner][plugin];
    }

    /// @inheritdoc IPRBProxyRegistry
    function getMethodsByProxy(
        IPRBProxy proxy,
        IPRBProxyPlugin plugin
    ) external view returns (bytes4[] memory methods) {
        methods = _methods[proxy.owner()][plugin];
    }

    /// @inheritdoc IPRBProxyRegistry
    function getPermissionByOwner(
        address owner,
        address envoy,
        address target
    ) external view returns (bool permission) {
        permission = _permissions[owner][envoy][target];
    }

    /// @inheritdoc IPRBProxyRegistry
    function getPermissionByProxy(
        IPRBProxy proxy,
        address envoy,
        address target
    ) external view returns (bool permission) {
        permission = _permissions[proxy.owner()][envoy][target];
    }

    /// @inheritdoc IPRBProxyRegistry
    function getPluginByOwner(address owner, bytes4 method) external view returns (IPRBProxyPlugin plugin) {
        plugin = _plugins[owner][method];
    }

    /// @inheritdoc IPRBProxyRegistry
    function getPluginByProxy(IPRBProxy proxy, bytes4 method) external view returns (IPRBProxyPlugin plugin) {
        plugin = _plugins[proxy.owner()][method];
    }

    /// @inheritdoc IPRBProxyRegistry
    function getProxy(address user) external view returns (IPRBProxy proxy) {
        proxy = _proxies[user];
    }

    /// @inheritdoc IPRBProxyRegistry
    function isProxy(address user) external view override returns (bool) {
        return address(_owners[IPRBProxy(user)]) != address(0);
    }

    /*//////////////////////////////////////////////////////////////////////////
                         USER-FACING NON-CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @inheritdoc IPRBProxyRegistry
    function deploy() external override onlyNonProxyOwner(msg.sender) returns (IPRBProxy proxy) {
        proxy = _deploy({owner: msg.sender, target: address(0), data: ""});
    }

    /// @inheritdoc IPRBProxyRegistry
    function deployAndExecute(
        address target,
        bytes calldata data
    ) external override onlyNonProxyOwner(msg.sender) returns (IPRBProxy proxy) {
        proxy = _deploy({owner: msg.sender, target: target, data: data});
    }

    /// @inheritdoc IPRBProxyRegistry
    function deployFor(address user) external override onlyNonProxyOwner(user) returns (IPRBProxy proxy) {
        proxy = _deploy({owner: user, target: address(0), data: ""});
    }

    /// @inheritdoc IPRBProxyRegistry
    function deployAndExecuteAndInstallPlugin(
        address target,
        bytes calldata data,
        IPRBProxyPlugin plugin
    ) external override onlyNonProxyOwner(msg.sender) returns (IPRBProxy proxy) {
        proxy = _deploy({owner: msg.sender, target: target, data: data});
        _installPlugin(plugin);
    }

    /// @inheritdoc IPRBProxyRegistry
    function deployAndInstallPlugin(
        IPRBProxyPlugin plugin
    ) external onlyNonProxyOwner(msg.sender) returns (IPRBProxy proxy) {
        proxy = _deploy({owner: msg.sender, target: address(0), data: ""});
        _installPlugin(plugin);
    }

    /// @inheritdoc IPRBProxyRegistry
    function installPlugin(IPRBProxyPlugin plugin) external override onlyCallerWithProxy {
        _installPlugin(plugin);
    }

    /// @inheritdoc IPRBProxyRegistry
    function setPermission(address envoy, address target, bool permission) external override onlyCallerWithProxy {
        address owner = msg.sender;
        _permissions[owner][envoy][target] = permission;
        emit SetPermission(owner, _proxies[owner], envoy, target, permission);
    }

    /// @inheritdoc IPRBProxyRegistry
    function uninstallPlugin(IPRBProxyPlugin plugin) external override onlyCallerWithProxy {
        // Retrieve the methods originally installed by this plugin.
        address owner = msg.sender;
        bytes4[] memory methods = _methods[owner][plugin];

        // The plugin must be a known, previously installed plugin.
        uint256 length = methods.length;
        if (length == 0) {
            revert PRBProxyRegistry_PluginUnknown(plugin);
        }

        // Uninstall every method in the list.
        for (uint256 i = 0; i < length; ) {
            delete _plugins[owner][methods[i]];
            unchecked {
                i += 1;
            }
        }

        // Remove the methods from the reverse mapping.
        delete _methods[owner][plugin];

        // Log the plugin uninstallation.
        emit UninstallPlugin(owner, _proxies[owner], plugin, methods);
    }

    /*//////////////////////////////////////////////////////////////////////////
                          INTERNAL NON-CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @dev See the documentation for the user-facing functions that call this internal function.
    function _deploy(address owner, address target, bytes memory data) internal returns (IPRBProxy proxy) {
        // Use the address of the owner as the CREATE2 salt.
        bytes32 salt = bytes32(abi.encodePacked(owner));

        // Set the owner and empty out the target and the data to prevent reentrancy.
        constructorParams = ConstructorParams({owner: owner, target: target, data: data});

        // Deploy the proxy with CREATE2.
        proxy = new PRBProxy{salt: salt}();
        delete constructorParams;

        // Associate the owner and the proxy.
        _proxies[owner] = proxy;
        _owners[proxy] = owner;
        // Log the creation of the proxy.
        emit DeployProxy({operator: msg.sender, owner: owner, proxy: proxy});
    }

    /// @dev See the documentation for the user-facing functions that call this internal function.
    function _installPlugin(IPRBProxyPlugin plugin) internal {
        // Retrieve the methods to install.
        bytes4[] memory methods = plugin.getMethods();

        // The plugin must implement at least one method.
        uint256 length = methods.length;
        if (length == 0) {
            revert PRBProxyRegistry_PluginWithZeroMethods(plugin);
        }

        // Install every method in the list.
        address owner = msg.sender;
        for (uint256 i = 0; i < length; ) {
            // Check for collisions.
            bytes4 method = methods[i];
            if (address(_plugins[owner][method]) != address(0)) {
                revert PRBProxyRegistry_PluginMethodCollision({
                    currentPlugin: _plugins[owner][method],
                    newPlugin: plugin,
                    method: method
                });
            }
            _plugins[owner][method] = plugin;
            unchecked {
                i += 1;
            }
        }

        // Set the methods in the reverse mapping.
        _methods[owner][plugin] = methods;

        // Log the plugin installation.
        emit InstallPlugin(owner, _proxies[owner], plugin, methods);
    }

    function getAddress(address owner) public view returns (address) {
        bytes32 salt = bytes32(abi.encodePacked(owner));

        bytes memory bytecode = abi.encodePacked(type(PRBProxy).creationCode);

        bytes32 hash = keccak256(
            abi.encodePacked(
                bytes1(0xff),      
                address(this),     
                salt,              
                keccak256(bytecode)
            )
        );

        return address(uint160(uint(hash)));
    }

}
IPRBProxy.sol 66 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

import { IPRBProxyPlugin } from "./IPRBProxyPlugin.sol";
import { IPRBProxyRegistry } from "./IPRBProxyRegistry.sol";

/// @title IPRBProxy
/// @notice Proxy contract to compose transactions on behalf of the owner.
interface IPRBProxy {
    /*//////////////////////////////////////////////////////////////////////////
                                       ERRORS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Thrown when a target contract reverts without a specified reason.
    error PRBProxy_ExecutionReverted();

    /// @notice Thrown when an unauthorized account tries to execute a delegate call.
    error PRBProxy_ExecutionUnauthorized(address owner, address caller, address target);

    /// @notice Thrown when the fallback function fails to find an installed plugin for the method selector.
    error PRBProxy_PluginNotInstalledForMethod(address caller, address owner, bytes4 method);

    /// @notice Thrown when a plugin execution reverts without a specified reason.
    error PRBProxy_PluginReverted(IPRBProxyPlugin plugin);

    /// @notice Thrown when a non-contract address is passed as the target.
    error PRBProxy_TargetNotContract(address target);

    /*//////////////////////////////////////////////////////////////////////////
                                       EVENTS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Emitted when a target contract is delegate called.
    event Execute(address indexed target, bytes data, bytes response);

    /// @notice Emitted when a plugin is run for a provided method.
    event RunPlugin(IPRBProxyPlugin indexed plugin, bytes data, bytes response);

    /*//////////////////////////////////////////////////////////////////////////
                                 CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice The address of the owner account or contract, which controls the proxy.
    function owner() external view returns (address);

    /// @notice The address of the registry that has deployed this proxy.
    function registry() external view returns (IPRBProxyRegistry);

    /*//////////////////////////////////////////////////////////////////////////
                               NON-CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Delegate calls to the provided target contract by forwarding the data. It returns the data it
    /// gets back, and bubbles up any potential revert.
    ///
    /// @dev Emits an {Execute} event.
    ///
    /// Requirements:
    /// - The caller must be either the owner or an envoy with permission.
    /// - `target` must be a contract.
    ///
    /// @param target The address of the target contract.
    /// @param data Function selector plus ABI encoded data.
    /// @return response The response received from the target contract, if any.
    function execute(address target, bytes calldata data) external payable returns (bytes memory response);
}
IPRBProxyPlugin.sol 19 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

/// @title IPRBProxyPlugin
/// @notice Interface for plugin contracts that can be installed on a proxy.
/// @dev Plugins are contracts that enable the proxy to interact with and respond to calls from other contracts. These
/// plugins are run via the proxy's fallback function.
///
/// This interface is meant to be directly inherited by plugin implementations.
interface IPRBProxyPlugin {
    /// @notice Retrieves the methods implemented by the plugin.
    /// @dev The registry pulls these methods when installing the plugin.
    ///
    /// Requirements:
    /// - The plugin must implement at least one method.
    ///
    /// @return methods The array of the methods implemented by the plugin.
    function getMethods() external returns (bytes4[] memory methods);
}
IPRBProxyRegistry.sol 265 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

import {IPRBProxy} from "prb-proxy/interfaces/IPRBProxy.sol";
import {IPRBProxyPlugin} from "prb-proxy/interfaces/IPRBProxyPlugin.sol";

/// @title IPRBProxyRegistry
/// @notice Deploys new proxies via CREATE2 and keeps a registry of owners to proxies. Proxies can only be deployed
/// once per owner, and they cannot be transferred. The registry also supports installing plugins, which are used
/// for extending the functionality of the proxy.
interface IPRBProxyRegistry {
    /*//////////////////////////////////////////////////////////////////////////
                                       ERRORS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Thrown when trying to install a plugin that implements a method already implemented by another
    /// installed plugin.
    error PRBProxyRegistry_PluginMethodCollision(
        IPRBProxyPlugin currentPlugin,
        IPRBProxyPlugin newPlugin,
        bytes4 method
    );

    /// @notice Thrown when trying to uninstall an unknown plugin.
    error PRBProxyRegistry_PluginUnknown(IPRBProxyPlugin plugin);

    /// @notice Thrown when trying to install a plugin that doesn't implement any method.
    error PRBProxyRegistry_PluginWithZeroMethods(IPRBProxyPlugin plugin);

    /// @notice Thrown when a function requires the user to have a proxy.
    error PRBProxyRegistry_UserDoesNotHaveProxy(address user);

    /// @notice Thrown when a function requires the user to not have a proxy.
    error PRBProxyRegistry_UserHasProxy(address user, IPRBProxy proxy);

    /*//////////////////////////////////////////////////////////////////////////
                                       EVENTS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Emitted when a new proxy is deployed.
    event DeployProxy(address indexed operator, address indexed owner, IPRBProxy proxy);

    /// @notice Emitted when a plugin is installed.
    event InstallPlugin(
        address indexed owner,
        IPRBProxy indexed proxy,
        IPRBProxyPlugin indexed plugin,
        bytes4[] methods
    );

    /// @notice Emitted when an envoy's permission is updated.
    event SetPermission(
        address indexed owner,
        IPRBProxy indexed proxy,
        address indexed envoy,
        address target,
        bool newPermission
    );

    /// @notice Emitted when a plugin is uninstalled.
    event UninstallPlugin(
        address indexed owner,
        IPRBProxy indexed proxy,
        IPRBProxyPlugin indexed plugin,
        bytes4[] methods
    );

    /*//////////////////////////////////////////////////////////////////////////
                                      STRUCTS
    //////////////////////////////////////////////////////////////////////////*/

    /// @param owner The address of the user who will own the proxy.
    /// @param target The address of the target to delegate call to. Can be set to zero.
    /// @param data The call data to be passed to the target. Can be set to zero.
    struct ConstructorParams {
        address owner;
        address target;
        bytes data;
    }

    /*//////////////////////////////////////////////////////////////////////////
                                 CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice The release version of the proxy system, which applies to both the registry and deployed proxies.
    /// @dev This is stored in the registry rather than the proxy to save gas for end users.
    function VERSION() external view returns (string memory);

    /// @notice The parameters used in constructing the proxy, which the registry sets transiently during proxy
    /// deployment.
    /// @dev The proxy constructor fetches these parameters.
    function constructorParams() external view returns (address owner, address target, bytes memory data);

    /// @notice Retrieves the list of installed methods for the provided plugin.
    /// @dev An empty array is returned if the plugin is unknown.
    /// @param owner The proxy owner for the query.
    /// @param plugin The plugin for the query.
    function getMethodsByOwner(address owner, IPRBProxyPlugin plugin) external view returns (bytes4[] memory methods);

    /// @notice Retrieves the list of installed methods for the provided plugin.
    /// @dev An empty array is returned if the plugin is unknown.
    /// @param proxy The proxy for the query.
    /// @param plugin The plugin for the query.
    function getMethodsByProxy(IPRBProxy proxy, IPRBProxyPlugin plugin) external view returns (bytes4[] memory methods);

    /// @notice Retrieves a boolean flag that indicates whether the provided envoy has permission to call the provided
    /// target.
    /// @param owner The proxy owner for the query.
    /// @param envoy The address checked for permission to call the target.
    /// @param target The address of the target.
    function getPermissionByOwner(address owner, address envoy, address target) external view returns (bool permission);

    /// @notice Retrieves a boolean flag that indicates whether the provided envoy has permission to call the provided
    /// target.
    /// @param proxy The proxy for the query.
    /// @param envoy The address checked for permission to call the target.
    /// @param target The address of the target.
    function getPermissionByProxy(
        IPRBProxy proxy,
        address envoy,
        address target
    ) external view returns (bool permission);

    /// @notice Retrieves the address of the plugin installed for the provided method selector.
    /// @dev The zero address is returned if no plugin is installed.
    /// @param owner The proxy owner for the query.
    /// @param method The method selector for the query.
    function getPluginByOwner(address owner, bytes4 method) external view returns (IPRBProxyPlugin plugin);

    /// @notice Retrieves the address of the plugin installed for the provided method selector.
    /// @dev The zero address is returned if no plugin is installed.
    /// @param proxy The proxy for the query.
    /// @param method The method selector for the query.
    function getPluginByProxy(IPRBProxy proxy, bytes4 method) external view returns (IPRBProxyPlugin plugin);

    /// @notice Retrieves the proxy for the provided user.
    /// @param user The user address for the query.
    function getProxy(address user) external view returns (IPRBProxy proxy);

    /// @notice Retrieves a boolean flag that indicates whether the provided address is a registered proxy.
    /// @param proxy The proxy address for the query.
    function isProxy(address proxy) external view returns (bool);

    /*//////////////////////////////////////////////////////////////////////////
                               NON-CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Deploys a new proxy for the caller.
    ///
    /// @dev Emits a {DeployProxy} event.
    ///
    /// Requirements:
    /// - The caller must not have a proxy.
    ///
    /// @return proxy The address of the newly deployed proxy.
    function deploy() external returns (IPRBProxy proxy);

    /// @notice This function performs two actions:
    /// 1. Deploys a new proxy for the caller
    /// 2. Delegate calls to the provided target, returning the data it gets back, and bubbling up any potential revert.
    ///
    /// @dev Emits a {DeployProxy} and {Execute} event.
    ///
    /// Requirements:
    /// - The caller must not have a proxy.
    /// - `target` must be a contract.
    ///
    /// @param target The address of the target.
    /// @param data Function selector plus ABI-encoded data.
    /// @return proxy The address of the newly deployed proxy.
    function deployAndExecute(address target, bytes calldata data) external returns (IPRBProxy proxy);

    /// @notice This function performs three actions:
    /// 1. Deploys a new proxy for the caller
    /// 2. Delegate calls to the provided target, returning the data it gets back, and bubbling up any potential revert.
    /// 3. Installs the provided plugin on the newly deployed proxy.
    ///
    /// @dev Emits a {DeployProxy}, {Execute}, and {InstallPlugin} event.
    ///
    /// Requirements:
    /// - The caller must not have a proxy.
    /// - See the requirements in `installPlugin`.
    /// - See the requirements in `execute`.
    ///
    /// @param target The address of the target.
    /// @param data Function selector plus ABI-encoded data.
    /// @param plugin The address of the plugin to install.
    /// @return proxy The address of the newly deployed proxy.
    function deployAndExecuteAndInstallPlugin(
        address target,
        bytes calldata data,
        IPRBProxyPlugin plugin
    ) external returns (IPRBProxy proxy);

    /// @notice This function performs two actions:
    /// 1. Deploys a new proxy for the caller.
    /// 2. Installs the provided plugin on the newly deployed proxy.
    ///
    /// @dev Emits a {DeployProxy} and {InstallPlugin} event.
    ///
    /// Requirements:
    /// - The caller must not have a proxy.
    /// - See the requirements in `installPlugin`.
    ///
    /// @param plugin The address of the plugin to install.
    /// @return proxy The address of the newly deployed proxy.
    function deployAndInstallPlugin(IPRBProxyPlugin plugin) external returns (IPRBProxy proxy);

    /// @notice Deploys a new proxy for the provided user.
    ///
    /// @dev Emits a {DeployProxy} event.
    ///
    /// Requirements:
    /// - The user must not have a proxy already.
    ///
    /// @param user The address that will own the proxy.
    /// @return proxy The address of the newly deployed proxy.
    function deployFor(address user) external returns (IPRBProxy proxy);

    /// @notice Installs the provided plugin on the caller's proxy, and saves the list of methods implemented by the
    /// plugin so that they can be referenced later.
    ///
    /// @dev Emits an {InstallPlugin} event.
    ///
    /// Notes:
    /// - Installing a plugin is a potentially dangerous operation, because anyone can run the plugin.
    /// - Plugin methods that have the same selectors as {IPRBProxy.execute}, {IPRBProxy.owner}, and
    /// {IPRBProxy.registry} can be installed, but they can never be run.
    ///
    /// Requirements:
    /// - The caller must have a proxy.
    /// - The plugin must have at least one implemented method.
    /// - There must be no method collision with any other plugin installed by the caller.
    ///
    /// @param plugin The address of the plugin to install.
    function installPlugin(IPRBProxyPlugin plugin) external;

    /// @notice Gives or takes a permission from an envoy to call the provided target and function selector
    /// on behalf of the caller's proxy.
    ///
    /// @dev Emits a {SetPermission} event.
    ///
    /// Notes:
    /// - It is not an error to set the same permission.
    ///
    /// Requirements:
    /// - The caller must have a proxy.
    ///
    /// @param envoy The address of the account the caller is giving or taking permission from.
    /// @param target The address of the target.
    /// @param permission The boolean permission to set.
    function setPermission(address envoy, address target, bool permission) external;

    /// @notice Uninstalls the plugin from the caller's proxy, and removes the list of methods originally implemented by
    /// the plugin.
    ///
    /// @dev Emits an {UninstallPlugin} event.
    ///
    /// Requirements:
    /// - The caller must have a proxy.
    /// - The plugin must be a known, previously installed plugin.
    ///
    /// @param plugin The address of the plugin to uninstall.
    function uninstallPlugin(IPRBProxyPlugin plugin) external;
}
PRBProxy.sol 136 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.18;

import { IPRBProxy } from "./interfaces/IPRBProxy.sol";
import { IPRBProxyPlugin } from "./interfaces/IPRBProxyPlugin.sol";
import { IPRBProxyRegistry } from "./interfaces/IPRBProxyRegistry.sol";

/*

██████╗ ██████╗ ██████╗ ██████╗ ██████╗  ██████╗ ██╗  ██╗██╗   ██╗
██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔═══██╗╚██╗██╔╝╚██╗ ██╔╝
██████╔╝██████╔╝██████╔╝██████╔╝██████╔╝██║   ██║ ╚███╔╝  ╚████╔╝
██╔═══╝ ██╔══██╗██╔══██╗██╔═══╝ ██╔══██╗██║   ██║ ██╔██╗   ╚██╔╝
██║     ██║  ██║██████╔╝██║     ██║  ██║╚██████╔╝██╔╝ ██╗   ██║
╚═╝     ╚═╝  ╚═╝╚═════╝ ╚═╝     ╚═╝  ╚═╝ ╚═════╝ ╚═╝  ╚═╝   ╚═╝

*/

/// @title PRBProxy
/// @dev See the documentation in {IPRBProxy}.
contract PRBProxy is IPRBProxy {
    /*//////////////////////////////////////////////////////////////////////////
                                     CONSTANTS
    //////////////////////////////////////////////////////////////////////////*/

    /// @inheritdoc IPRBProxy
    address public immutable override owner;

    /// @inheritdoc IPRBProxy
    IPRBProxyRegistry public immutable override registry;

    /*//////////////////////////////////////////////////////////////////////////
                                     CONSTRUCTOR
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Creates the proxy by fetching the constructor params from the registry, optionally delegate calling
    /// to a target contract if one is provided.
    /// @dev The rationale of this approach is to have the proxy's CREATE2 address not depend on any constructor params.
    constructor() {
        registry = IPRBProxyRegistry(msg.sender);
        (address owner_, address target, bytes memory data) = registry.constructorParams();
        owner = owner_;
        if (target != address(0)) {
            _execute(target, data);
        }
    }

    /*//////////////////////////////////////////////////////////////////////////
                                  FALLBACK FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Fallback function used to run plugins.
    /// @dev WARNING: anyone can call this function and thus run any installed plugin.
    fallback(bytes calldata data) external payable returns (bytes memory response) {
        // Check if the function selector points to a known installed plugin.
        IPRBProxyPlugin plugin = registry.getPluginByOwner({ owner: owner, method: msg.sig });
        if (address(plugin) == address(0)) {
            revert PRBProxy_PluginNotInstalledForMethod({ caller: msg.sender, owner: owner, method: msg.sig });
        }

        // Delegate call to the plugin.
        bool success;
        (success, response) = address(plugin).delegatecall(data);

        // Log the plugin run.
        emit RunPlugin(plugin, data, response);

        // Check if the call was successful or not.
        if (!success) {
            // If there is return data, the delegate call reverted with a reason or a custom error, which we bubble up.
            if (response.length > 0) {
                assembly {
                    let returndata_size := mload(response)
                    revert(add(32, response), returndata_size)
                }
            } else {
                revert PRBProxy_PluginReverted(plugin);
            }
        }
    }

    /// @dev Called when `msg.value` is not zero and the call data is empty.
    receive() external payable { }

    /*//////////////////////////////////////////////////////////////////////////
                         USER-FACING NON-CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @inheritdoc IPRBProxy
    function execute(address target, bytes calldata data) external payable override returns (bytes memory response) {
        // Check that the caller is either the owner or an envoy with permission.
        if (owner != msg.sender) {
            bool permission = registry.getPermissionByOwner({ owner: owner, envoy: msg.sender, target: target });
            if (!permission) {
                revert PRBProxy_ExecutionUnauthorized({ owner: owner, caller: msg.sender, target: target });
            }
        }

        // Delegate call to the target contract, and handle the response.
        response = _execute(target, data);
    }

    /*//////////////////////////////////////////////////////////////////////////
                          INTERNAL NON-CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Executes a DELEGATECALL to the provided target with the provided data.
    /// @dev Shared logic between the constructor and the `execute` function.
    function _execute(address target, bytes memory data) internal returns (bytes memory response) {
        // Check that the target is a contract.
        if (target.code.length == 0) {
            revert PRBProxy_TargetNotContract(target);
        }

        // Delegate call to the target contract.
        bool success;
        (success, response) = target.delegatecall(data);

        // Log the execution.
        emit Execute(target, data, response);

        // Check if the call was successful or not.
        if (!success) {
            // If there is return data, the delegate call reverted with a reason or a custom error, which we bubble up.
            if (response.length > 0) {
                assembly {
                    // The length of the data is at `response`, while the actual data is at `response + 32`.
                    let returndata_size := mload(response)
                    revert(add(response, 32), returndata_size)
                }
            } else {
                revert PRBProxy_ExecutionReverted();
            }
        }
    }
}
IPRBProxyRegistry.sol 267 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

import { IPRBProxy } from "./IPRBProxy.sol";
import { IPRBProxyPlugin } from "./IPRBProxyPlugin.sol";

/// @title IPRBProxyRegistry
/// @notice Deploys new proxies via CREATE2 and keeps a registry of owners to proxies. Proxies can only be deployed
/// once per owner, and they cannot be transferred. The registry also supports installing plugins, which are used
/// for extending the functionality of the proxy.
interface IPRBProxyRegistry {
    /*//////////////////////////////////////////////////////////////////////////
                                       ERRORS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Thrown when trying to install a plugin that implements a method already implemented by another
    /// installed plugin.
    error PRBProxyRegistry_PluginMethodCollision(
        IPRBProxyPlugin currentPlugin, IPRBProxyPlugin newPlugin, bytes4 method
    );

    /// @notice Thrown when trying to uninstall an unknown plugin.
    error PRBProxyRegistry_PluginUnknown(IPRBProxyPlugin plugin);

    /// @notice Thrown when trying to install a plugin that doesn't implement any method.
    error PRBProxyRegistry_PluginWithZeroMethods(IPRBProxyPlugin plugin);

    /// @notice Thrown when a function requires the user to have a proxy.
    error PRBProxyRegistry_UserDoesNotHaveProxy(address user);

    /// @notice Thrown when a function requires the user to not have a proxy.
    error PRBProxyRegistry_UserHasProxy(address user, IPRBProxy proxy);

    /*//////////////////////////////////////////////////////////////////////////
                                       EVENTS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Emitted when a new proxy is deployed.
    event DeployProxy(address indexed operator, address indexed owner, IPRBProxy proxy);

    /// @notice Emitted when a plugin is installed.
    event InstallPlugin(
        address indexed owner, IPRBProxy indexed proxy, IPRBProxyPlugin indexed plugin, bytes4[] methods
    );

    /// @notice Emitted when an envoy's permission is updated.
    event SetPermission(
        address indexed owner, IPRBProxy indexed proxy, address indexed envoy, address target, bool newPermission
    );

    /// @notice Emitted when a plugin is uninstalled.
    event UninstallPlugin(
        address indexed owner, IPRBProxy indexed proxy, IPRBProxyPlugin indexed plugin, bytes4[] methods
    );

    /*//////////////////////////////////////////////////////////////////////////
                                      STRUCTS
    //////////////////////////////////////////////////////////////////////////*/

    /// @param owner The address of the user who will own the proxy.
    /// @param target The address of the target to delegate call to. Can be set to zero.
    /// @param data The call data to be passed to the target. Can be set to zero.
    struct ConstructorParams {
        address owner;
        address target;
        bytes data;
    }

    /*//////////////////////////////////////////////////////////////////////////
                                 CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice The release version of the proxy system, which applies to both the registry and deployed proxies.
    /// @dev This is stored in the registry rather than the proxy to save gas for end users.
    function VERSION() external view returns (string memory);

    /// @notice The parameters used in constructing the proxy, which the registry sets transiently during proxy
    /// deployment.
    /// @dev The proxy constructor fetches these parameters.
    function constructorParams() external view returns (address owner, address target, bytes memory data);

    /// @notice Retrieves the list of installed methods for the provided plugin.
    /// @dev An empty array is returned if the plugin is unknown.
    /// @param owner The proxy owner for the query.
    /// @param plugin The plugin for the query.
    function getMethodsByOwner(address owner, IPRBProxyPlugin plugin) external view returns (bytes4[] memory methods);

    /// @notice Retrieves the list of installed methods for the provided plugin.
    /// @dev An empty array is returned if the plugin is unknown.
    /// @param proxy The proxy for the query.
    /// @param plugin The plugin for the query.
    function getMethodsByProxy(
        IPRBProxy proxy,
        IPRBProxyPlugin plugin
    )
        external
        view
        returns (bytes4[] memory methods);

    /// @notice Retrieves a boolean flag that indicates whether the provided envoy has permission to call the provided
    /// target.
    /// @param owner The proxy owner for the query.
    /// @param envoy The address checked for permission to call the target.
    /// @param target The address of the target.
    function getPermissionByOwner(
        address owner,
        address envoy,
        address target
    )
        external
        view
        returns (bool permission);

    /// @notice Retrieves a boolean flag that indicates whether the provided envoy has permission to call the provided
    /// target.
    /// @param proxy The proxy for the query.
    /// @param envoy The address checked for permission to call the target.
    /// @param target The address of the target.
    function getPermissionByProxy(
        IPRBProxy proxy,
        address envoy,
        address target
    )
        external
        view
        returns (bool permission);

    /// @notice Retrieves the address of the plugin installed for the provided method selector.
    /// @dev The zero address is returned if no plugin is installed.
    /// @param owner The proxy owner for the query.
    /// @param method The method selector for the query.
    function getPluginByOwner(address owner, bytes4 method) external view returns (IPRBProxyPlugin plugin);

    /// @notice Retrieves the address of the plugin installed for the provided method selector.
    /// @dev The zero address is returned if no plugin is installed.
    /// @param proxy The proxy for the query.
    /// @param method The method selector for the query.
    function getPluginByProxy(IPRBProxy proxy, bytes4 method) external view returns (IPRBProxyPlugin plugin);

    /// @notice Retrieves the proxy for the provided user.
    /// @param user The user address for the query.
    function getProxy(address user) external view returns (IPRBProxy proxy);

    /*//////////////////////////////////////////////////////////////////////////
                               NON-CONSTANT FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Deploys a new proxy for the caller.
    ///
    /// @dev Emits a {DeployProxy} event.
    ///
    /// Requirements:
    /// - The caller must not have a proxy.
    ///
    /// @return proxy The address of the newly deployed proxy.
    function deploy() external returns (IPRBProxy proxy);

    /// @notice This function performs two actions:
    /// 1. Deploys a new proxy for the caller
    /// 2. Delegate calls to the provided target, returning the data it gets back, and bubbling up any potential revert.
    ///
    /// @dev Emits a {DeployProxy} and {Execute} event.
    ///
    /// Requirements:
    /// - The caller must not have a proxy.
    /// - `target` must be a contract.
    ///
    /// @param target The address of the target.
    /// @param data Function selector plus ABI-encoded data.
    /// @return proxy The address of the newly deployed proxy.
    function deployAndExecute(address target, bytes calldata data) external returns (IPRBProxy proxy);

    /// @notice This function performs three actions:
    /// 1. Deploys a new proxy for the caller
    /// 2. Delegate calls to the provided target, returning the data it gets back, and bubbling up any potential revert.
    /// 3. Installs the provided plugin on the newly deployed proxy.
    ///
    /// @dev Emits a {DeployProxy}, {Execute}, and {InstallPlugin} event.
    ///
    /// Requirements:
    /// - The caller must not have a proxy.
    /// - See the requirements in `installPlugin`.
    /// - See the requirements in `execute`.
    ///
    /// @param target The address of the target.
    /// @param data Function selector plus ABI-encoded data.
    /// @param plugin The address of the plugin to install.
    /// @return proxy The address of the newly deployed proxy.
    function deployAndExecuteAndInstallPlugin(
        address target,
        bytes calldata data,
        IPRBProxyPlugin plugin
    )
        external
        returns (IPRBProxy proxy);

    /// @notice This function performs two actions:
    /// 1. Deploys a new proxy for the caller.
    /// 2. Installs the provided plugin on the newly deployed proxy.
    ///
    /// @dev Emits a {DeployProxy} and {InstallPlugin} event.
    ///
    /// Requirements:
    /// - The caller must not have a proxy.
    /// - See the requirements in `installPlugin`.
    ///
    /// @param plugin The address of the plugin to install.
    /// @return proxy The address of the newly deployed proxy.
    function deployAndInstallPlugin(IPRBProxyPlugin plugin) external returns (IPRBProxy proxy);

    /// @notice Deploys a new proxy for the provided user.
    ///
    /// @dev Emits a {DeployProxy} event.
    ///
    /// Requirements:
    /// - The user must not have a proxy already.
    ///
    /// @param user The address that will own the proxy.
    /// @return proxy The address of the newly deployed proxy.
    function deployFor(address user) external returns (IPRBProxy proxy);

    /// @notice Installs the provided plugin on the caller's proxy, and saves the list of methods implemented by the
    /// plugin so that they can be referenced later.
    ///
    /// @dev Emits an {InstallPlugin} event.
    ///
    /// Notes:
    /// - Installing a plugin is a potentially dangerous operation, because anyone can run the plugin.
    /// - Plugin methods that have the same selectors as {IPRBProxy.execute}, {IPRBProxy.owner}, and
    /// {IPRBProxy.registry} can be installed, but they can never be run.
    ///
    /// Requirements:
    /// - The caller must have a proxy.
    /// - The plugin must have at least one implemented method.
    /// - There must be no method collision with any other plugin installed by the caller.
    ///
    /// @param plugin The address of the plugin to install.
    function installPlugin(IPRBProxyPlugin plugin) external;

    /// @notice Gives or takes a permission from an envoy to call the provided target and function selector
    /// on behalf of the caller's proxy.
    ///
    /// @dev Emits a {SetPermission} event.
    ///
    /// Notes:
    /// - It is not an error to set the same permission.
    ///
    /// Requirements:
    /// - The caller must have a proxy.
    ///
    /// @param envoy The address of the account the caller is giving or taking permission from.
    /// @param target The address of the target.
    /// @param permission The boolean permission to set.
    function setPermission(address envoy, address target, bool permission) external;

    /// @notice Uninstalls the plugin from the caller's proxy, and removes the list of methods originally implemented by
    /// the plugin.
    ///
    /// @dev Emits an {UninstallPlugin} event.
    ///
    /// Requirements:
    /// - The caller must have a proxy.
    /// - The plugin must be a known, previously installed plugin.
    ///
    /// @param plugin The address of the plugin to uninstall.
    function uninstallPlugin(IPRBProxyPlugin plugin) external;
}

Read Contract

VERSION 0xffa1ad74 → string
_owners 0xbf3a5c02 → address
constructorParams 0x66b0182d → address, address, bytes
getAddress 0xae22c57d → address
getMethodsByOwner 0xfa557e93 → bytes4[]
getMethodsByProxy 0x6383afb2 → bytes4[]
getPermissionByOwner 0xb31d1b99 → bool
getPermissionByProxy 0x5cabcdf7 → bool
getPluginByOwner 0x61be4859 → address
getPluginByProxy 0x1ddef5b9 → address
getProxy 0xb7fba4d3 → address
isProxy 0x29710388 → bool

Write Contract 8 functions

These functions modify contract state and require a wallet transaction to execute.

deploy 0x775c300c
No parameters
returns: address
deployAndExecute 0x092af813
address target
bytes data
returns: address
deployAndExecuteAndInstallPlugin 0x9d1bd159
address target
bytes data
address plugin
returns: address
deployAndInstallPlugin 0xfb4a4d08
address plugin
returns: address
deployFor 0x74912cd2
address user
returns: address
installPlugin 0xb9678403
address plugin
setPermission 0xaa4b826a
address envoy
address target
bool permission
uninstallPlugin 0x4bddd93a
address plugin

Recent Transactions

No transactions found for this address