Proxies (or "diamonds", which is just a name for a specific proxy system specified as an EIP) allow part or all of a contract to be swapped out at any time, without changing the address of the primary entry point for the contract. The entry point simply stores the address of the latest implementation (which may be changed by the contract owner), and then it forwards any function calls to the address of the latest implementation. Proxies were developed because contract deployment is irreversible: the code of a deployed contract can never be changed. But contract storage can be changed. So at the deployment address, the proxy code is deployed, along with the forwarding address of the actual contract you want users to call. Then any function call to the proxy address will just be forwarded to the actual target contract. There are a couple more functions in the proxy contract that allow the owner of the contract to update the forwarding address. This is how the proxied "real" contract can be updated.
Proxies are less safe non-proxied contracts if you don't trust the contract owners (since the owners can swap out the implementation at any time, screwing with their users however they want), but they are more safe than non-proxied contracts if you do trust the contract owners (since the owners can fix bugs at any time).
If a security bug is found in a contract implementation, and it was not deployed to work through a proxy, then the only way to fix the security bug is to:
- Freeze all activity on the buggy contract, if your API even has a call to accomplish that (but adding that sort of API will reduce user confidence in your contract if they don't trust you).
- Fix the bug to create a new bug-free version of the contract.
- Make a complete copy of the data structures of the old contract, reversing any damaging changes to account balances etc. that were made by hackers, if the vulnerability was actively exploited. (Note that this may cause a ripple effect of bugs on other contracts, such as exchanges, since they expect that the "rug won't be pulled out from under them", i.e. that account balances etc. will not suddenly change in unexpected ways. This issue is true even for proxied contracts, if you try to fix any damage done, by overriding behavior directly.)
- Deploy the fixed data structures along with the new bug-free version of the code (this can be very expensive if the old contract has grown a lot in its storage requirements over time).
- Instruct your users to use the new copy of the contract, at the new deployment address (who knows if you will even be able to reach all users who need to know).
- Ask your old contract to
SELFDESTRUCT
, if you even have an API to do that (but adding that sort of API will also reduce user confidence in your contract if they don't trust you).
- Hope that all other contracts that need to call your contract (such as exchanges) see your notice that your contract address has changed.
- Hope that people trust that the newly deployed contract is the official replacement for the buggy old contract (scammers could probably impersonate the authors of the buggy contract to claim there was a new bugfixed version, and take over the ecosystem).
So you can probably see, proxied contracts are the way to go if you are deploying a contract as a trustworthy/trusted individual or organization, because the above alternative is pretty terrible.
On the flip side, whether or not you are not a trustworthy/trusted individual or organization, if you deploy without a proxy, the chance of an exploitable vulnerability being found in the contract is fairly high, and that may undermine users' confidence in your contract. Therefore not deploying with a proxy may be more anxiety-inducing for users than deploying with a proxy!
If you are not a trustworthy/trusted individual or organization, and you want to avoid a dubious response to deploying your contract via a proxy, then you need to invest in an unbiased security audit of your contract before deploying it. But these can run anywhere from tens to hundreds of thousands of dollars.
If you do get a security audit, Etherscan has a way of submitting the URL to the audit results, which can then be officially associated with your contract, so that people can see it's trustworthy. Although even if you deploy an audited contract, but you deploy with a proxy, there's nothing stopping you from coming back later and swapping out the implementation with one that contains some nefarious bug. (You will lose your Etherscan source verification if you do that though, since the proxied contract will no longer have the same hashcode as the old one you verified with source, unless you submit the nefarious source for verification.)
EtherScan can detect whether a contract is proxied, in many circumstances:
https://medium.com/etherscan-blog/and-finally-proxy-contract-support-on-etherscan-693e3da0714b
https://etherscan.io/proxyContractChecker
When viewing a contract on EtherScan, under the "Contract" tab, if Etherscan knows the contract is proxied, then you will have not just "Read Contract" and "Write Contract", but also "Read Contract via Proxy" and "Write Contract via Proxy" or similar.
If the proxied code has been updated, Etherscan will show you the contract address for the previous version(s) of the code, so that users can examine all versions for changes.