Tuesday, April 30, 2024

190: Sablier

 The CodeHawks platform has an upcoming audit on the Sablier protocol, so I decided to read through the docs and familiarize myself with the existing deployments before the audit contest goes live. 

In traditional finance, payment is sent out in discrete lump sum amounts. These payments have numerous fundamental problems, such as being prone to human error and being controlled by numerous intermediaries. Sablier innovates on this concept by allowing continuous streams of payment in any ERC20 token. This technology enables numerous use cases not possible in traditional finance. Firstly Sablier allows for automated vesting, where payment can be sent out on a pre-defined bases to recipients without the need of constant work from a treasury team. The recipient receives a fraction of their allocated compensation every second, granting them more freedom in their finances. This model also eliminates Schelling points in the speculation of token prices. When vesting is done manually, the date and time of a distribution, if known, will effect the market itself. With continuous payment, there is no single discrete moment exists to create a coordinated disruptive market action. The transparency of the Sablier protocol also allows all payment streams to clearly defined in terms of purpose and duration. Errors can also be corrected early, as a payment to the wrong address can be canceled long before the full sum is transferred. 

Sablier also allows for a gradual airdrop stream when launching a new project. Often, crypto projects will airdrop their initial supply and the token will dump immediately when recipients sell. The stream method allows for the token supply to be gradually released over time. Additionally, the stream admin has the ability to cancel the steam to any recipient who has stopped engaging with the project. This airdrop management can promote project longevity. 

The protocol is built on the ER-1620 standard which was the first proposal on Ethereum for streaming payments. This supports simple linear lockups, where the token becomes available on a by-second basis. However, the programmability of the protocol allows for arbitrarily complex lockups. A "cliff" can be built, where tokens are accumulated but cannot be withdrawn before a certain date. Exponential or logarithmic lockups can be created, along with monthly distributions, or any combination of the above. The only real limitation is the function must be monotonic, since the claimable amount of tokens cannot decrease with time. 

Each stream is wrapped in an ERC-721 NFT which grants the owner the permission to withdraw the accumulated tokens. The NFT further creates DEFI opportunity, since the NFT itself can be traded or lent on a secondary market. 

Wednesday, April 24, 2024

189: ZKasino Rugpull

 The ZKasino project recently exit scammed over 33 million dollars worth of Ethereum. 

he recent debacle surrounding ZKasino offers valuable lessons for anyone involved in cryptocurrency investments. As investors and users grapple with the aftermath of the $33 million rug pull, it's essential to reflect on the warning signs that preceded the collapse and what can be learned from them.

    One of the earliest red flags was the founder's questionable past, including involvement in failed projects like ZigZagExchange. Prioritizing due diligence on the team behind a project can reveal potential risks and help investors assess the credibility of their claims.

     ZKasino touted advanced technologies like zkSync while operating on a more basic network. Such inconsistencies should prompt investors to scrutinize a project's claims and verify the accuracy of its technological capabilities.

    The sudden cancellation of token listings without clear explanations should raise concerns about the project's stability and integrity. Investors should be wary of projects that fail to communicate openly and transparently about significant developments or changes in plans.

    Reports of unpaid employees and contractors, as well as allegations of mismanagement within the team, can indicate underlying issues within a project. Investors should pay attention to such allegations and conduct thorough research before committing funds.

    Projects that make inflated promises of high returns with little substance behind them should be approached with caution. Investors should critically evaluate the feasibility of a project's goals and assess the likelihood of achieving them.

Wednesday, April 10, 2024

188: Remote Procedure Calls

Interacting directly with the Ethereum blockchain requires running a full Ethereum node locally. This can be a complex process involving downloading and synchronizing the entire Ethereum blockchain, and requires intensive resources including memory and network bandwidth. This is where the utility of Remote Procedure Calls (RPCs) come into Web3 development. 

An RPC allows a computer to call a procedure on another network, while abstracting away the specific details of how the procedure works or is processed. This concept far predates blockchain and goes back to the 1970s. In the context of Ethereum, RPC calls allow developers to interact with the blockchain and with smart contracts without having to personally handle all the complexities of deploying an Eth node. This provides an enormous utility and allowed Web3 applications to maintain a light footprint without the overhead of running a local node, while having all the power and capability to interact with the network. There are a variety of RPC providers, but Infura is a popular one with a generous free tier to allow for developers to practice working with decentralized applications. By abstracting away the complexities of working with the blockchain directly, RPC providers like Infura allow developers to focus on the business logic of their contracts and applications, making these providers a critical part of the entire Web3 ecosystem. 

Friday, March 29, 2024

187: msg.value

 In Soldity, msg.value is a global variable that represents the amount of ether sent along with a function call. The msg.value variable is commonly used when handling payments in smart contracts and to verify if the user has sent enough money along with the contract. This works as expected in simple contracts, but as code grows in complexity various security considerations emerge. The msg.value variable persists within its scope, so any kind of looping logic will read the same total value regardless of how the ether sent has been used. Attackers can leverage this in order to apply the same ether payment to multiple functions, essentially double counting their payment. 

A potentially catastrophic exploit of this nature was caught and fixed in SushiSwap before any funds were stolen. In 2021 SushiSwap had implemented a bidding contract for auctions that utilized the BoringBatchable library to submit batches of delegateCalls to other contracts within the system. The critical flaw overlooked by the SushiSwap team is that msg.value persists across delegateCalls. This allowed an attacker to submit a batch of bids with one ether payment, submitting bids for free and exploiting the action. The exploit became even more serious when combined with the contract's refund function. By counting the same msg.value payment multiple times, the attacker could manipulate the contract state to make it seem like they had deposited a large fortune of money, and then request it back as a refund, stealing all the ether that had been legitimately deposited by other users. 

Fortunately, the exploit was found and remedied before any attack can be made. This episode in 2021 illustrates how even a blue chip exchange like SushiSwap can push code with vulnerabilities, and the risks associated with handling global variables within complex logic where their scope can become obfuscated.

 To read about the experience of the original auditor in finding this exploit, click here

Wednesday, March 27, 2024

186: DOS in Web3

 Denial of Service (DOS) attacks render web3 protocols unusable and unable to provide value to their users. Many of these attacks derive from the gas requirement users pay to interact with a blockchain. In certain scenarios an attacker can burden a protocol to the point where the code needs to do a tremendous account of calculations and the gas cost becomes prohibitive to honest users. Often these vulnerabilities come from unbounded loops in Solidity code, where there is no upper limit to the amount of times the loop must iterate and repeat. For example, the Bridges exchange dividend system was vulnerable to a Denial of Service attack because an attacker could create an arbitrary amount of users to extend a loop indefinitely long. The protocol had no minimum amount required to mint a pair token, so the attacker could mint a single wei of pair tokens and bog the users list down for a negligible price. The Bridges fixed this by changing their dividend logic: each unit of owned supply was entitled to a certain amount of dividend that the user could withdraw at one time based on the amount of pair tokens they held. This way, the withdrawal is computed at the time of the transaction and no loop is required. 

Another example of of a Denial of Service attack was found in an audit of the GMX code. In GMX, a leveraged position will be liquidated if the collateral value goes too low, and any excess collateral is sent back to the address. In this case, an attacker could create a contract without either a receive() or fallback() function that is unable to receive ether, and use the contract to create their leveraged position. In the event of liquidation, GMX would attempt to send the leftover ETH collateral the address, but the transfer will fail and cause an unintended revert. The attacker has now created a position that is unable to be liquidated, exploiting the system and threatening the solvency of the protocol. GMX fixed this by sending wrapped ERC20 ether as a backup in case the native transfer failed, solving the denial of service exploit on their liquidation function. 


When auditing code we can ask the following questions to identify DOS vulnerability:

1) Is a loop iterating a boundless number of iterations? Can a user add iterations to the loop? How much does it cost the user to add more iterations to the loop? 

2) Look for any external calls such as sending Ether to a contract. Is there a way for that call to fail? Is it possible for the external call to run out of gas? If it does, will it cause the top level transaction to fail? And how will that effect the overall system? 

Saturday, March 23, 2024

185: Encoded Function Calls

 Normally functions are called in a smart contract at a high level within a Solidity file, using the functions name and arguments. Solidity also supports the low level .call function which allows the direct calling of an encoded function. This is a powerful feature that allows us to interact with dynamically loaded contracts and to interface with contracts whose source is unavailable. The function signature and arguments are converted into a byte array using the ABI, and are passed as function calldata to the contract address, where it is then decoded and executed. Encoded function calls enable upgradeable smart contracts despite the immutable nature of deployed code on a blockchain. We can create a proxy contract who extracts call data and sends them to the implementation contract. Then at a later time, a new upgraded implementation contract can be deployed and the forwarding address updated in the proxy contract. The proxy contract remains unchanged, and the upgrade process appears seamless to external users. Overall encoded function calls allow developers to separate concerns of logic and data, and create resilient and flexible decentralized applications. 

Wednesday, January 3, 2024

184: Smart Contracts on Hedera

In addition to its native SDK, Hedera also supports smart contracts in a platform compatible with the Ethereum Virtual Machine. This allows for a great deal of interopability with Ethereum and the crypto ecosystem as a whole, where Solidity smart contract code can be ported to Hedera with little modification. The hashgraph technology allows for a high level of scalability, and the fees to deploy and interact with the smart contract are often extremely cheap, only fractions of an HBAR. 

In order to get started, I created a fresh account on the Hedera developer portal and was granted two accounts, one of which has an EVM address and we use for smart contracts. I imported the Hedera Testnet as a custom network within my Metamask wallet and linked it with the HEX encoded private key, and saw my testnet HBARs. From here I wrote a simple smart contract in Remix and deployed it with the injected Metamask provider, and all deployment fees were paid in testnet HBAR. From here I could look up the contract EVM address on Hashscan.io and see more information about it, along with its Hedera account ID. 

190: Sablier

 The CodeHawks platform has an upcoming audit on the Sablier protocol, so I decided to read through the docs and familiarize myself with the...