Vejo que OpenZeppelinTransparentProxy
é compatível. Existem planos para adicionar suporte de proxy UUPS em um futuro próximo?
Planejando oferecer suporte nativo, mas por enquanto ainda é possível usá-los com o implante de hardhat. o proxy precisa ter um argumento de proprietário fictício / não utilizado em seu construtor para permanecer compatível.
o proxy precisa ter um argumento de proprietário fictício / não utilizado em seu construtor para permanecer compatível.
Isso não faria com que o uso do UUPS deixasse de ser benéfico? O motivo de usar o UUPS é economizar gás nas chamadas de transação, porque o proxy não precisa verificar se é o administrador que está fazendo a chamada.
Talvez eu esteja perdendo, você poderia explicar com algum pseudocódigo como usar o hardhat-deploy com uups proxies (com o argumento não utilizado)?
Obrigado
Não afetará o gás, é apenas um argumento fictício para que o hardhat-deploy possa implantá-lo sem mudança de código. o construtor não precisa fazer nada com esse argumento.
Vou ver se consigo fazer a alteração para que funcione sem qualquer alteração em breve. deve ser uma pequena mudança onde você pode especificar o argumento do construtor para o proxy ou talvez simplesmente especificar que é um proxy UUPS
Obrigado @wighawag , finalmente
Para os interessados criei este contrato:
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
// Kept for backwards compatibility with older versions of Hardhat and Truffle plugins.
contract UUPSProxy is ERC1967Proxy {
constructor(
address _logic,
address, // This is completely unused by the uups proxy, required to remain compatible with hardhat deploy: https://github.com/wighawag/hardhat-deploy/issues/146
bytes memory _data
) payable ERC1967Proxy(_logic, _data) {}
}
E então minhas implantações se parecem com isto ( proxyContract: "UUPSProxy"
sendo a parte importante):
await deploy(CONTRACT, {
from: deployer,
proxy: {
proxyContract: "UUPSProxy",
// ... your other config, initializers etc
},
log: true,
});
@JasoonS Por favor, você pode esclarecer o propósito desse código de contrato UUPSProxy
? É apenas um contrato fictício para que o hardhat-deploy conheça a interface do construtor do proxy real? Ou ele realmente se relaciona de alguma forma com o contrato de proxy que é implantado?
Qual é exatamente a função de admin
, eu obtenho um erro não importa se está lá, o deployer
(= upgrade admin) ou se omito o campo.
proxy: {
proxyContract: "UUPSProxy",
execute: {
methodName: "initialize",
args: [admin],
},
},
@marceljay Por favor (sempre) cole o (s) erro (s) que você obtiver :-)
Olá @aspiers , Não cavei profundamente no hardhat-deploy, então corrija-me @wighawag. Mas pelo que entendi sabe como implantar proxies transparentes. E os proxies transparentes são implantados com um administrador que gerencia esses proxies. Em contratos UUPS, você não tem um contrato externo (proxy admin) gerenciando as atualizações, ele está na própria implementação - portanto, não é passado para o construtor de proxy.
Então, para fazer isso funcionar com o hardhat-deploy, nós o implantamos com o mesmo construtor de um proxy transparente, mas apenas ignoramos o campo admin e obtemos o mesmo efeito.
Parece estar funcionando para mim @marceljay
Isenção de responsabilidade meu snippet de código não foi auditado: sweat_smile: - Não me responsabilizo por proxies mal configurados: rindo:
@marceljay Ah, sim, posso adivinhar o seu problema. Eu editei minha resposta original.
O código a seguir é o que fazer na implementação. Portanto, tenho uma função na implementação (não o proxy) chamada initialize que leva em 1 argumento (o admin).
execute: {
methodName: "initialize",
args: [admin],
},
@marceljay Ah, sim, posso adivinhar o seu problema. Eu editei minha resposta original.
O código a seguir é o que fazer na implementação. Portanto, tenho uma função na implementação (não o proxy) chamada initialize que leva em 1 argumento (o admin).
execute: { methodName: "initialize", args: [admin], },
Sim, agora faz todo o sentido, vi que você editou a resposta :)
Você sabe se o contrato ERC1967Proxy
é o mesmo que é usado pelo plug-in de atualizações OZ?
@JasoonS Graças um lote para as explicações, mas eu ainda não entendo completamente. Acima, você postou um contrato começando:
contract UUPSProxy is ERC1967Proxy {
Isso realmente é implantado de verdade pelo código de amostra await deploy
que você postou acima ou é apenas um contrato fictício para que o hardhat-deploy conheça a interface do construtor do proxy real ou algo mais? Você escreveu:
nós o implantamos com o mesmo construtor de um proxy transparente
mas se estiver realmente implantando isso, não vejo como poderia funcionar, porque esse contrato herda de ERC1967Proxy
não UUPSUpgradeable
, então de onde viria a funcionalidade UUPS real?
Isso realmente é implantado de verdade pelo código de amostra, aguarda implantação que você postou acima?
Sim, ele realmente o implanta.
porque esse contrato herda de ERC1967Proxy e não UUPSUpgradeable
Ele deve usar o ERC1967Proxy (UUPS e proxies transparentes do openzeppelin usam erc1967, https://docs.openzeppelin.com/contracts/4.x/api/proxy#transparent-vs-uups). O contrato UUPSUpgradeable
é usado pelo contrato de implementação (não faz parte do proxy).
então, de onde viria a funcionalidade UUPS real?
Por design, o contrato de implementação mantém a funcionalidade UUPS, (o que é bom porque é mais eficiente em termos de gás, uma vez que a lógica não está no próprio proxy, mas ruim porque é possível atualizar para um contrato não compatível por engano e interromper a capacidade de atualização )
Além disso, definitivamente não sou um especialista em proxies, isso veio apenas de minha própria pesquisa.
@JasoonS comentou em 1º de setembro de 2021 21:18 :
porque esse contrato herda de ERC1967Proxy e não UUPSUpgradeable
Ele deve usar o ERC1967Proxy (UUPS e proxies transparentes do openzeppelin usam erc1967, docs.openzeppelin.com/contracts/4.x/api/proxy#transparent-vs-uups ).
Direito. E o ERC-1967 não faz muito, exceto especificar o local de armazenamento do endereço de implementação, endereço de beacon e endereço de administrador. BTW fato engraçado que notei: em conformidade com ERC-1967, a implementação OZ UUPS na verdade viola EIP1822 que especifica um local de armazenamento ligeiramente diferente para o endereço de implementação.
O contrato
UUPSUpgradeable
é usado pelo contrato de implementação (não faz parte do proxy).
D'oh, é claro! Obrigado por me ajudar a ver o que eu estava perdendo estupidamente aqui.
então, de onde viria a funcionalidade UUPS real?
Por design, o contrato de implementação mantém a funcionalidade UUPS, (o que é bom porque é mais eficiente em termos de gás, uma vez que a lógica não está no próprio proxy, mas ruim porque é possível atualizar para um contrato não compatível por engano e interromper a capacidade de atualização )
Sim, então a implementação deve herdar de UUPSUpgradeable
.
Muito obrigado novamente por esta grande ajuda!
Comentários muito úteis
Planejando oferecer suporte nativo, mas por enquanto ainda é possível usá-los com o implante de hardhat. o proxy precisa ter um argumento de proprietário fictício / não utilizado em seu construtor para permanecer compatível.