░░░                              ░░░             ▀▄
                       ▄ ▀▀▄              ░░░          ░░░
                     ▄      ▒        ▄▄                ▒    ▄▀       ▒           ▀▄
                     ▄             ▄                ▄█    █       ▄▀           ▀▀     ▀▀ ▄
                      ▀█▄▄▄▄▄██▀███▄▄      ▄▄█▄▄ ▄▀▄▄▀  ▄▄ ▄▄▄▀
                      ▀▀▄▄  █▄▀     ▄▄ ▀▀▀▀  ▀▄▄██▀▀▌  ▐          ▄█▀▀▀▄ ▄▄    ░░      ■▀ ▀▄       ▄▀▀ ██▀▄
                          ██       ▓▓     ██    ██         ▐▌██  ▄█    ██            
                          ▀█       ██░░    ▓▓  █▄     ██  ▓▓                  
                         ▓█      ▀█▄▄▄▀   ▒▒     ░░▒▒    ▒▒  ░░  ▐▌ ██      ▄▄▄          
                        █▓      ▀▀▄▄▄▄▄▓▓▀▄█   █▓  ▓  ▌▓   ▀██  ▄▄
           ▄╬▄             ▓▒       █▓     ▀▀   █▓  ▓█    █▓  ▓█ ▌  ▓▓  ▓▓█ ▄▀█▓     ▄█         ▄╬▄
      ,    █▌    ,              ▓█    ░░▄▄     ░▓  █▓ █▐        █▓    ,    ▐█    ,
        █▌    ░░▀▀▀▀ ██       ▀▄ ░░░▄▄ ░  ▓░    ▀█▐ ▐▌   ▌█  ░░         ▐█   
       ▀█▓█▓█▀    ▀▄ ░░░░     ▀▄▀▒       █▓▄▀▀▄▀░░    █▀▀▓█       ▓█ ▄▓ ▄▄   ▀█▓█▓█▀  
           ▀▓%           ▀▄     ░░     ▄▀  ▄▀     █▀  ▀█    ▀▄▄   ▄▄▀   ▒▀ █▄  ▀█    ▄▀       %▓▀      
                      ▀▄        ▄▄▀      ▄▀          ▀▄     ▄▀    ▄▄      ▄▀  ■▄                          
▀▀▄▄▄█▄▒                                             ▀█                ▄▀      ▀▄                ▒▄█▄▄▄▀▀
    ▄▄▀                                        
 ▒▄[ Arte por L.Ayres ]▄▒ 
  ▒                                                                                                                ▒ 
  █                                                                                                                █ 
 Como drenar empresas Web3
 ▒▒          Caue                                                                                                  ▒▒
  ▒                                                                                                                ▒ 
 Já se perguntou o porque dos bug bounties de Web3/blockchain serem tão altos?
 Bom, isso é porque, diferente de uma empresa do mercado tradicional, toda a sua
 ▒▒          segurança está baseada em recursos tecnológicos e não há bloqueios centralizados                      ▒▒
 que bloqueiem hacks.
  █                                                                                                                █ 
 Por exemplo, se uma conta de banco de uma empresa for invadida, é claro que o
 ▒▒          hacker conseguiria fazer um bom estrago, mas por questões de segurança do banco,                      ▒▒
 ele não conseguiria roubar todo o dinheiro do caixa da empresa. No caso da
 blockchain, se o hacker consegue acesso à private key de uma conta é game over,
  ¡        todo o esforço que a empresa colocou para crescer vai pro /dev/null. Além disso,                      ▒▒
  ▒,       sabemos que a bolha Web3 movimenta muito dinheiro e é atrativa para hackers por
  █▀▀°       conta do certo nível de anonimidade que é possível de obter.
 ▒▒                                                                                                                ▒▒
 Mas como que é possível acessar os fundos de uma empresa se hoje em dia existe
 tecnologia o suficiente para proteger chaves privadas de forma praticamente
 inviolável (Exemplo: Trezor, Ledger, …)? É tudo phishing?
 ▒▒                                                                                                                ▒▒
 Negativo, falhas de lógica no código da operação da empresa são a principal
 forma que os protocolos/dApps são hackeados. Apesar de existirem wallets para
 armazenar chaves privadas de forma segura, esses produtos tiram uma das
 ▒▒          vantagens da blockchain, que é a transferência de dinheiro de forma programática                      ▒▒
 sem intermediação. Isso implica que, para que a operação de algumas empresas
 funcione corretamente, eles precisam armazenar essas chaves em um local
 acessível pelo código da aplicação web para que seja possível interagir com a
 ▒▒          blockchain. Outra opção é não utilizar aplicações web e colocar toda a lógica do                    ¡ ▒▒
 produto em um smart contract, que é o que a maioria faz.                                           ,
 °▀▀
 ▒▒          Portanto, existem 2 formas que conseguimos interagir (de forma indireta) com os                       ▒▒
 fundos da empresa na blockchain:
  █                                                                                                                █ 
 1. Aplicações Web e Chaves de Custódia: Aplicações que realizam operações em
 ▒▒          nome do usuário ou da própria empresa (necessitando acesso programático a uma                         ▒▒
 private key custodiada).
 2. Smart Contracts: Colocando toda a lógica do produto diretamente na
 blockchain, permitindo transferências de valor e interações programáticas sem
 ▒▒          intermediários.                                                                                       ▒▒
  ▒                                                                                                                ▒ 
 Como a maioria dos dApps (Descentralized Apps) e protocolos usam smart contracts
 como sua lógica e custódia de tokens principal, é lá onde se deve encontrar uma
  ¡        falha de lógica para ser possível drenar os fundos da conta. Porém, normalmente,                      ▒▒
  ▒,       os smart contracts são auditados várias vezes e por várias empresas diferentes,
  █▀▀°       portanto é bem difícil encontrar bugs críticos lá. Entretanto, existem outros
 ▒▒          ataques que podem ser feitos em aplicações web específicas que também podem                           ▒▒
 levar à LoF (Loss of Funds). Nesse artigo vou dar alguns exemplos de falhas de
 lógica que já encontrei em aplicações reais de blockchain que poderiam levar à
 drains.
 ▒▒                                                                                                                ▒▒
 Situação 1 - Off-chain transaction sponsorship
  █                                                                                                                █ 
 Para entender essa vulnerabilidade, primeiro é preciso entender o básico de como
 ▒▒          uma transação (tx) na blockchain funciona. Embora cada chain tenha suas                               ▒▒
 especificidades, a maioria delas possui uma taxa de transação chamada de “gas
 fee”, que normalmente deve ser paga com a moeda nativa da blockchain (ex: na
 rede Solana, se deve pagar o gas fee com SOL). Algumas blockchains também
 ▒▒          possuem uma feature de “sponsorship”, que permite que uma “sponsor account”                         ¡ ▒▒
 pague o gas fee por uma transação que não foi iniciada por ele. Para que isso                      ,
 aconteça, o sponsor deve ser especificado na transação e também deve ser um                        °▀▀
 ▒▒          signer dessa transação (assinar a tx com a sua chave privada).                                        ▒▒
  ▒                                                                                                                ▒ 
 Em solana, o sponsor é sempre o primeiro signer da transação (`signatures[0] ==
 sponsor`) [1]:
 ▒▒                                                                                                                ▒▒
 pub struct Transaction {
  #[wasm_bindgen(skip)]
  #[serde(with = "short_vec")]
 ▒▒           pub signatures: Vec<Signature>,                                                                      ▒▒
  #[wasm_bindgen(skip)]
  pub message: Message,
 }
  ¡                                                                                                              ▒▒
  ▒,
  █▀▀°       Não é tão incomum que algumas aplicações utilizem da feature de sponsorship para
 ▒▒          diminuir a barreira de entrada e captar mais usuários (por exemplo: a transação                       ▒▒
 para criação de novas contas é sponsored pela aplicação - custo 0 para o
 usuário). Normalmente essa feature está disponível por uma API HTTP, onde o
 usuário envia uma transação, a API valida se é uma transação válida e segura e,
 ▒▒          caso seja, a transação é assinada pela chave privada da sponsor account e é                           ▒▒
 devolvida ao usuário.
  █                                                                                                                █ 
 // isso é um pseudocódigo
 ▒▒          app.post('/sponsor', (req, res) => {                                                                  ▒▒
         isValid = await validateTransaction(req.tx);
  █                                                                                                                █ 
         if (isValid){
 ▒▒                          signedTx = keypair.signTransaction(req.tx)                                          ¡ ▒▒
                 res.json(signedTx) // a transação é serializada com todas as informações           ,
 (incluindo as assinaturas)                                                                         °▀▀
 ▒▒                  }                                                                                             ▒▒
         else {
                 res.status(400).end()
         }
 ▒▒          });                                                                                                   ▒▒
  ▒                                                                                                                ▒ 
  █                                                                                                                █ 
 Sabendo como funciona, já é possível pensar nos ataques possíveis.
 ▒▒                                                                                                                ▒▒
 Ataque A - Gastando todos os tokens da sponsor account - DoS
  █                                                                                                                █ 
 Apesar dos gas fees geralmente serem valores baixos (depende da blockchain, mas
  ¡        na maioria é questão de centavos), caso a API não coloque um rate limit                               ▒▒
  ▒,       plausível, é possível que usuários maliciosos consigam efetuar várias transações
  █▀▀°       gastando os tokens da sponsor account para pagar o gas fee, o que pode levar à
 ▒▒          falência da sponsor account e, causar um DoS na aplicação já que ela depende dos                      ▒▒
 tokens da sponsor account para operações básicas.
  █                                                                                                                █ 
 Normalmente, esse ataque não é considerado tão crítico porque o atacante não
 ▒▒          consegue roubar o dinheiro para ele, portanto não existe tanta motivação para                         ▒▒
 efetuar esse ataque.
  █                                                                                                                █ 
 Ataque B - Bypassando a validação da transação
 ▒▒                                                                                                                ▒▒
 A vulnerabilidade mais crítica que pode ocorrer nessa feature é quando a
 transação não é validada corretamente. Vou explicar 2 casos que já encontrei em
 real life, uma em ambiente Solana e outro no Stellar.
 ▒▒                                                                                                              ¡ ▒▒
 Caso 1 - Solana sponsorship hack                                                                   ,
 °▀▀
 ▒▒          O caso do ambiente solana é um pouco mais complicado de explicar sem dar muito                        ▒▒
 detalhes sobre a aplicação. Basicamente, ela utilizava de smart contracts para
 criar sessões (logins) de usuários dentro da blockchain, onde se você fizesse
 login com sua conta principal em um domínio, esse domínio só teria acesso à sua
 ▒▒          sessão, que era mais limitado do que a conta principal (restrição de token                            ▒▒
 allowance).
  █                                                                                                                █ 
         2. Inicia sessão para dApp1  +------------------------+
 ▒▒                +------------------------------+                        |                                       ▒▒
       |                              | Smart Contract da      |
       |  +---------------------------> Sessão                 |
       |  |                           +------------------------+
  ¡              |  |                                                                                            ▒▒
  ▒,             |  |
  █▀▀°             |  |                           +------------------------+
 ▒▒          +-----v--+----+  1.Obter sponsorship |                        |                                       ▒▒
 |             <----------------------+                        |
 |   Usuário   +----------------------> dApp 1 sponsorship API |
 |             |                      |                        |
 ▒▒          +--------+----+                      |                        |                                       ▒▒
          |                           +------------------------+
          |
          |
 ▒▒                   |                                                                                            ▒▒
          |
          |                             +-------------------+
          | 3. Manda a sessão para o app|                   |
 ▒▒                   +-----------------------------> dApp 1 (dapp1.com)|                                        ¡ ▒▒
                                        |                   |                                       ,
                                        +-------------------+                                       °▀▀
 ▒▒                                                                                                                ▒▒
  ▒                                                                                                                ▒ 
 A vuln encontrada aqui foi na validação da instrução, que permitia que a sponsor
 account do dApp1 pagasse pelos gas fees de uma início de sessão para o dApp2.
 ▒▒          Apesar de não ser uma vulnerabilidade tão crítica, ainda sim é possível utilizar                      ▒▒
 os fundos de outro projeto para financiar o seu malware ou site de phishing.
  █                                                                                                                █ 
         2. Inicia sessão para dApp2  +------------------------+
 ▒▒                +------------------------------+                        |                                       ▒▒
       |                              | Smart Contract da      |
       |  +---------------------------> Sessão                 |
       |  |                           +------------------------+
  ¡              |  |                                                                                            ▒▒
  ▒,             |  |
  █▀▀°             |  |                           +------------------------+
 ▒▒          +-----v--+----+  1.Obter sponsorship |                        |                                       ▒▒
 |             <----------------------+                        |
 |   Usuário   +----------------------> dApp 1 sponsorship API |
 |             |                      |                        |
 ▒▒          +--------+----+                      |                        |                                       ▒▒
          |                           +------------------------+
          |
          |
 ▒▒                   |                                                                                            ▒▒
          |
          |                             +-------------------+
          | 3. Manda a sessão para o app|                   |
 ▒▒                   +-----------------------------> dApp 2 (dapp2.com)|                                        ¡ ▒▒
                                        |                   |                                       ,
                                        +-------------------+                                       °▀▀
 ▒▒                                                                                                                ▒▒
  ▒                                                                                                                ▒ 
 Isso era possível porque a validação da transação não validava se a sessão sendo
 iniciada era para o mesmo dApp da sponsor account.
 ▒▒                                                                                                                ▒▒
 Caso 2 - Stellar sponsorship hack
  █                                                                                                                █ 
 O caso que eu encontrei em uma wallet da Stellar foi mais preocupante. A vuln
 ▒▒          permitia drenar todos os fundos presentes na sponsor account da wallet, que era                       ▒▒
 em torno de $150,000 na época do beta test. No caso da chain Stellar, as
 transações e instruções funcionam de forma um pouco diferente. Cada transação
 tem um array de “operations”, que funcionam como instruções, por exemplo:
  ¡                                                                                                              ▒▒
  ▒,       Transaction
  █▀▀°
 ▒▒          Operation 1 - CreateAccount                                                                           ▒▒
  ▒                                                                                                                ▒ 
 +---------------+-----------+--------------------------------------------------------------+
 | Campo         | Tipo      | Descrição                                                    |
 ▒▒          +---------------+-----------+--------------------------------------------------------------+          ▒▒
 | Destination   | AccountID | O ID da nova conta a ser criada.                             |
 | Starting      | Int64     | A quantidade inicial de XLM (Lumens) para financiar a nova   |
 | Balance       |           | conta. Deve ser suficiente para atender ao requisito de      |
 ▒▒          |               |           | reserva mínima.                                              |          ▒▒
 +---------------+-----------+--------------------------------------------------------------+
  █                                                                                                                █ 
  ▒                                                                                                                ▒ 
 ▒▒          Operation 2 - Payment                                                                               ¡ ▒▒
 ,
 +-------------+-----------+----------------------------------------------------------------+       °▀▀
 ▒▒          | Campo       | Tipo      | Descrição                                                      |          ▒▒
 +-------------+-----------+----------------------------------------------------------------+
 | Destination | AccountID | Conta que receberá o pagamento.                                |
 | Asset       | Asset     | O ativo a ser enviado. Pode ser XLM (nativo) ou um token       |
 ▒▒          |             |           | (emitido).                                                     |          ▒▒
 | Amount      | Int64     | A quantidade do ativo a ser enviada.                           |
 +-------------+-----------+----------------------------------------------------------------+
  ▒                                                                                                                ▒ 
 ▒▒                                                                                                                ▒▒
 Essa transação poderia ser usada para enviar criar uma nova conta primeiro e
 depois enviar token para ela (ou outra conta, dependendo do Destination).
  ▒                                                                                                                ▒ 
  ¡        Para transações com sponsorship na blockchain Stellar, existem 2 operações que                        ▒▒
  ▒,       devem ser usadas [2]:
  █▀▀°
 ▒▒          - BeginSponsoringFutureReserves                                                                       ▒▒
     - Parâmetro SourceAccount —> define o sponsor account, que deve ser um
 signer da transação
     - Parâmetro SponsoredID —> define a conta que será patrocinada pelo
 ▒▒          sponsor (a conta que não vai precisar pagar os gas fees ou outros custos)                             ▒▒
 - EndSponsoringFutureReserves
     - Parâmetro SourceAccount
  ▒                                                                                                                ▒ 
 ▒▒          Elas definem quais operações devem ser sponsored e quais não a partir do que                          ▒▒
 está no meio das duas operações. Por exemplo, se quisermos fazer o sponsor
 apenas da criação da conta, mas não do pagamento (levando como base o exemplo
 passado), devemos ter uma transação com as seguintes operações (com os devidos
 ▒▒          parâmetros setados corretamente):                                                                   ¡ ▒▒
 ,
 1. BeginSponsoringFutureReserves                                                                   °▀▀
 ▒▒          2. CreateAccount                                                                                      ▒▒
 3. EndSponsoringFutureReserves
 4. Payment
  ▒                                                                                                                ▒ 
 ▒▒          Levando em conta que a sponsor account também deve assinar a transação para que                       ▒▒
 ela seja validada e incluída na blockchain, uma API HTTP também é necessária
 para a validação e assinatura da transação. Agora que você já sabe como funciona
 o básico das transações e operações da Stellar, vamos ver como foi possível
 ▒▒          drenar a sponsor account da wallet.                                                                   ▒▒
  ▒                                                                                                                ▒ 
 O principal erro cometido foi a falta de validação dos parâmetros globais
 opcionais. Se você olhar na documentação da Stellar para uma operação, você vai
  ¡        ver só os parâmetros específicos daquela operação (ex: Payment):                                      ▒▒
  ▒,
  █▀▀°       Payment
 ▒▒                                                                                                                ▒▒
 Sends an amount in a specific asset to a destination account.
  █                                                                                                                █ 
 SDKs: JavaScript | Java | Go  
 ▒▒          Threshold: Medium                                                                                     ▒▒
 Result: PaymentResult
  █                                                                                                                █ 
 Parameters
 ▒▒                                                                                                                ▒▒
 +-------------+------------+---------------------------------------------+
 | Parameter   | Type       | Description                                 |
 +-------------+------------+---------------------------------------------+
 ▒▒          | Destination | account ID | Account address that receives the payment.  |                          ¡ ▒▒
 | Asset       | asset      | Asset to send to the destination account.   |                         ,
 | Amount      | integer    | Amount of the aforementioned asset to send. |                         °▀▀
 ▒▒          +-------------+------------+---------------------------------------------+                            ▒▒
  ▒                                                                                                                ▒ 
  █                                                                                                                █ 
 Porém, toda operação também possui o parâmetro opcional SourceAccount , que
 ▒▒          dita qual conta que é responsável por realizar aquela operação (no caso do                            ▒▒
 Payment, qual conta que vai fazer o pagamento). Caso o parâmetro não seja
 setado, o usuário que iniciou a transação que irá ser o SourceAccount padrão [6].
  ▒                                                                                                                ▒ 
 ▒▒          No caso da wallet, eles não validavam isso em uma operação Payment e permitiam                        ▒▒
 eu enviar uma transação com o SourceAccount = sponsorAccount. Isso passava
 pela validação da transação e a assinatura da sponsor account era incluida. Uma
 vez que o sponsor account “aceitou a transação” (por conta da assinatura estar
  ¡        incluída), o pagamento era feito a partir da conta do sponsor account para o                          ▒▒
  ▒,       destino escolhido. Dessa forma, era possível drenar todos os fundos que a
  █▀▀°       sponsor account tinha ($150,000 no momento).
 ▒▒                                                                                                                ▒▒
 Situação 2 - Depósitos em Exchanges
  █                                                                                                                █ 
 Outra situação que envolve blockchain que é possível de ser exploitada é quando
 ▒▒          os depósitos em exchanges são validados de forma incorreta. Isso geralmente                           ▒▒
 ocorre pela complexidade de lidar com várias blockchains diferentes, que possuem
 detalhes técnicos diferentes. Vou explicar alguns casos que já encontrei em uma
 das minhas auditorias.
 ▒▒                                                                                                                ▒▒
 Caso 1: XRP deposit (deprecated)
  █                                                                                                                █ 
 O cliente havia implementado o depósito de crypto em XRP, que possui uma
 ▒▒          blockchain própria (XRPL). O problema nesse caso foi que a forma que a transação                    ¡ ▒▒
 de depósito era validada não estava correta pela existência de uma feature da                      ,
 chain XRP. Apesar de ser uma vulnerabilidade conhecida e bem documentada [3], quem                 °▀▀
 ▒▒          está implementando o depósito não espera que exista essa peculiaridade e acaba                        ▒▒
 achando que é só mais uma blockchain inserida na lista de criptomoedas aceitas
 como depósito.
  ▒                                                                                                                ▒ 
 ▒▒          Primeiro, para entender o exploit, precisamos ver como funciona uma transação de                      ▒▒
 pagamento no XRPL:
  █                                                                                                                █ 
 {
 ▒▒            "TransactionType": "Payment",                                                                       ▒▒
   "Account": "rSenderAccountID....................",
   "Destination": "rRecipientAccountID.................",
   "Amount": "100000000",
  ¡          "Fee": "12",                                                                                        ▒▒
  ▒,         "Sequence": 123456,
  █▀▀°         "Flags": 0,
 ▒▒            "SigningPubKey":                                                                                    ▒▒
 "ED................................................................",
   "TxnSignature":
 "......................................................"
 ▒▒          }                                                                                                     ▒▒
  ▒                                                                                                                ▒ 
  █                                                                                                                █ 
 Vemos que o o pagamento será feito em XRP (já que nenhum outro token foi
 ▒▒          especificado) com o Amount sendo 100000000 drops (10^-6 XRP) ou 1 XRP.                                ▒▒
 Entretanto, existe uma feature no XRP que são os “Partial Payments”, que permite
 que uma transação seja bem sucedida mesmo pagando um valor menor que o
 especificado no campo Amount , que tem alguns use cases quando você não quer
 ▒▒          que a transação reverta totalmente quando não há liquidez de um token.                              ¡ ▒▒
 ,
 Portanto, imagine que uma exchange verifique o valor do depósito a partir do                       °▀▀
 ▒▒          campo Amount :                                                                                        ▒▒
  ▒                                                                                                                ▒ 
 // pseudocodigo
 function validateDeposit(tx){
 ▒▒                  deposited_value = tx.Amount                                                                   ▒▒
  ▒                                                                                                                ▒ 
         if (tx.status == "tesSUCCESS"){
                 return deposited_value
 ▒▒                  }                                                                                             ▒▒
 }
  █                                                                                                                █ 
  ▒                                                                                                                ▒ 
  ¡        Em uma situação como essa, é possível exploitar a exchange:                                           ▒▒
  ▒,
  █▀▀°       1. Um atacante envia uma transação com o flag tfPartialPayment ativado e
 ▒▒          com o campo Amount definido para um valor muito alto (ex: 1.000.000 USD).                             ▒▒
 2. A transação é executada e, devido a limitações (falta de liquidez), entrega
 apenas um valor muito pequeno (ex: 1 USD). O resultado da transação é
 tesSUCCESS.
 ▒▒          3. Se a exchange ou o gateway vulnerável verificar apenas o campo Amount                              ▒▒
 (o valor máximo que o atacante disse que queria enviar) e não o valor real
 entregue (que é armazenado no campo DeliveredAmount da transação), a
 exchange credita os 1.000.000 USD ao atacante, em vez do 1 USD real.
 ▒▒                                                                                                                ▒▒
 É importante ressaltar que o campo Amount foi renomeado para DeliverMax
 alguns meses atrás, portanto acredito estar mais difícil dos desenvolvedores se
 confundirem e deixarem as exchanges vulneráveis.
 ▒▒                                                                                                              ¡ ▒▒
 Caso 2: Invalid success check                                                                      ,
 °▀▀
 ▒▒          Outro caso de exchanges sendo vulneráveis na feature de depósito aconteceu com a                      ▒▒
 Kraken e foi reportado em seu bug bounty (de forma meio controversa). O hacker
 descobriu que a Kraken não validava corretamente se o depósito foi bem sucedido
 em blockchains que usam EVM (Ethereum Virtual Machine) [4].
 ▒▒                                                                                                                ▒▒
 Para entender os detalhes, é preciso saber que redes Ethereum-like possuem
 internal transactions para uma transação. Quando uma função de um smart contract
 chama outra função, isso gera uma internalTx, porém, é importante ressaltar que
 ▒▒          elas podem ser chamadas de 2 formas:                                                                  ▒▒
  ▒                                                                                                                ▒ 
 1. Forma convencional
  ▒                                                                                                                ▒ 
  ¡        contract ContratoA {                                                                                  ▒▒
  ▒,           // Endereço do ContratoB para a chamada
  █▀▀°           ContratoB public B;
 ▒▒                                                                                                                ▒▒
     // Construtor: Vincula ContratoA ao endereço do ContratoB
     teste(address _enderecoContratoB) public {
         // Cria uma instância do ContratoB na memória, apontando para o endereço
 ▒▒          real                                                                                                  ▒▒
         B = ContratoB(_enderecoContratoB);
         B.teste(); // chama contratoB.teste() ---> Internal Tx
     }
 ▒▒                                                                                                                ▒▒
  ▒                                                                                                                ▒ 
 Nesse caso, se a chamada para B.teste() falhar/reverter, toda a transação é
 revertida, lembrando que a transação principal é a chamada para
 ▒▒          ContratoA.teste().                                                                                  ¡ ▒▒
 ,
 1. Forma Crua (Raw) [5]                                                                            °▀▀
 ▒▒                                                                                                                ▒▒
 contract ContratoA {
     // Endereço do ContratoB para a chamada
     ContratoB public B;
 ▒▒                                                                                                                ▒▒
     // Construtor: Vincula ContratoA ao endereço do ContratoB
     teste(address _enderecoContratoB) public {
         // Cria uma instância do ContratoB na memória, apontando para o endereço
 ▒▒          real                                                                                                  ▒▒
         B = ContratoB(_enderecoContratoB);
  █                                                                                                                █ 
               bytes memory data = abi.encodeWithSelector(
  ¡                    bytes4(keccak256("teste()")),                                                             ▒▒
  ▒,               ); // discriminator
  █▀▀°
 ▒▒                  (bool sucesso, bytes memory returndata) = B.call(data); // chama                              ▒▒
 contratoB.teste() ---> Internal Tx
     }
  ▒                                                                                                                ▒ 
 ▒▒                                                                                                                ▒▒
 Nesse caso, se a internal transaction reverter, a transação principal não
 reverte automaticamente. Ao invés disso, o sucesso ou não da internal
 transaction é retornado e deve ser checado de forma manual.
 ▒▒                                                                                                                ▒▒
 Agora, que você sabe como as internal transactions funciona, vamos ver como
 funcionava o exploit:
  ▒                                                                                                                ▒ 
 ▒▒          Fluxo do Ataque (Fluxograma)                                                                        ¡ ▒▒
 ,
                          ┌───────────────────────────┐                                             °▀▀
 ▒▒                                     Attack.controlAttack()                                                   ▒▒
                          └───────────────┬───────────┘
                                          
                                           Chamada externa para si mesmo
 ▒▒                                                    Permite que o nível superior                               ▒▒
                                           ignore o revert que ocorre abaixo
                                          
                        (! NÃO reverte neste nível!)
 ▒▒                                                                                                               ▒▒
                                          
                          ┌───────────────────────────┐
                              Attack.doDeposit()     
  ¡                                 └───────────────┬───────────┘                                                ▒▒
  ▒,                                                
  █▀▀°                                                 doDeposit() é basicamente:
 ▒▒                                                      transfer()                                               ▒▒
                                             revert()
                                          
                                (! ISTO REVERTE !)
 ▒▒                                                                                                               ▒▒
                                          
                          ┌──────────────────────────────┐
                            Depósito Matic para Kraken  
 ▒▒                                   └──────────────────────────────┘                                             ▒▒
  ▒                                                                                                                ▒ 
  █                                                                                                                █ 
 Trecho de Código Relevante (O que acontece internamente)
 ▒▒                                                                                                              ¡ ▒▒
 function 0xb6852ff9(address varg0, uint256 varg1) public nonPayable {                              ,
     require(4 + (msg.data.length - 4) - 4 >= 64);                                                  °▀▀
 ▒▒                                                                                                                ▒▒
     v0 = v1 = msg.sender == _sender;
     if (msg.sender != _sender) {
         v0 = msg.sender == address(this);
 ▒▒              }                                                                                                 ▒▒
  ▒                                                                                                                ▒ 
     require(v0, Error("Only owner."));
     v2 = varg0.call().value(varg1).gas(!varg1 * 2300);
 ▒▒                                                                                                                ▒▒
     require(bool(v2), 0, RETURNDATASIZE());
     require(varg1 < 1, Error("revert"));
 }
  ¡                                                                                                              ▒▒
  ▒,
  █▀▀°       Como é possível ver, o código do exploit era mais ou menos assim:
 ▒▒                                                                                                                ▒▒
 contract Attack {
         controlAttack() public {
                 bytes memory data = abi.encodeWithSelector(
 ▒▒                  bytes4(keccak256("doDeposit()")),                                                             ▒▒
     ); // discriminator
  █                                                                                                                █ 
     address(this).call(data);
 ▒▒                  }                                                                                             ▒▒
  ▒                                                                                                                ▒ 
         doDeposit() public {
                 address("KrakenDepositAddress").transfer(100000000000000); //
 ▒▒          envia 100000 wei (0.0001 ETH) para o endereço de deposito da kraken                                 ¡ ▒▒
                 revert();                                                                          ,
         }                                                                                          °▀▀
 ▒▒                                                                                                                ▒▒
  ▒                                                                                                                ▒ 
 Aqui, o atacante consegue enviar 0.00001 ETH para o endereço e depois reverter a
 transação interna (a que chama doDeposit()), mas não reverter a transação
 ▒▒          inteira. Provavelmente, o validador de depósito da kraken só validava se a                            ▒▒
 transação “pai” foi bem sucedida e não validava a internalTx que fez o depósito,
 fazendo com que os 0.00001 ETH fossem depositados na exchange, mas não fossem
 enviados para o endereço da blockchain.
 ▒▒                                                                                                                ▒▒
 No caso desses 2 ataques contra exchanges, se o exploit for bem sucedido você
 teria depositado tokens na exchange e, para drenar as reservas da plataforma só
 seria necessário realizar o saque (withdraw) dos tokens que foram depositados de
  ¡        forma maliciosa.                                                                                      ▒▒
  ▒,
  █▀▀°       Conclusão
 ▒▒                                                                                                                ▒▒
 Com a natureza irreversível da blockchain e que não oferece a segurança
 operacional dos sistemas financeiros tradicionais, a segurança se resume à
 perfeição do código. Os exemplos analisados — desde a exploração de
 ▒▒          patrocínio de transações (sponsorship) no Solana e Stellar até as falhas de                           ▒▒
 validação de depósitos em exchanges como a Kraken e o caso do XRP — demonstram
 que a principal vulnerabilidade reside em erros de lógica na interface entre
 as regras de negócio e os detalhes técnicos de cada chain. Espero que, caso o
 ▒▒          seu interesse seja procurar falhas em sistemas Web3, esse artigo tenha deixado                        ▒▒
 mais claro o tipo e classe de vulnerabilidades que são encontradas e que são
 consideradas críticas nesse ecossistema.
  ▒                                                                                                                ▒ 
 ▒▒          Referências                                                                                         ¡ ▒▒
 ,
 [1] https://solana.com/docs/core/transactions#signatures                                           °▀▀
 ▒▒          [2] https://developers.stellar.org/docs/build/guides/transactions/sponsored-reserves                  ▒▒
 [3] https://xrpl.org/docs/concepts/payment-types/partial-payments
 [4] https://x.com/danielvf/status/1803780167027871878
 [5] https://docs.soliditylang.org/en/latest/types.html#members-of-addresses
 ▒▒          [6] https://developers.stellar.org/docs/learn/fundamentals/transactions/list-of-operations            ▒▒
  ▒                                                                                                                ▒ 
  █                                                                                                                █ 
 ▒▒▒▒▒ ░░                                                                                                    ▒▒▒▒▒▒▒▒
                                                                                                                  ▓▄█
                                      T R A M O I A   ·   Z I N E   ·  2 0 2 6                                 gld ██
  ▀▄▄▄▄                                                                                                          ▒▒▄▄▀