SENTINEL

Deep Scan report, audit #1

Rubixi.sol

Score 57 out of 100, grade D

Source uploaded: 1 file, 104 lines of code, audited 19 Oct 2026, 12:00 UTC in 1 min 8 s.

SAUDIT #1verified onchainRubixi.solgrade D · 57/10019 Oct 2026TOKEN DETAILS
Collection
Sentinel Audit (SAUDIT)
Contract
0xfEA8…8c34
Token id
#1
Network
Base Sepolia · 84532
Metadata
fully onchain (tokenURI)
View on Basescan
Attestation NFT
SAUDIT #1
Read at block 48,334,267

Findings by severity

Critical1−10 pts
High3−15 pts
Medium5−10 pts
Low8−8 pts
Info40 pts

Where findings come from

  • Model and Slither agree9.5%2
  • Model only4.8%1
  • Slither only85.7%18

Confirmed by static analysis: 95.2%. AI only: 4.8%.

Models
cx/gpt-5.6-terra
Quorum reviewers
ag/claude-sonnet-4-6
Static analysis
Slither 0.11.6, solc 0.4.26, 34 detector results
Receipts
2 signed receipts, attester 0xef63…FdC5
Source hash
0x7a16ef…9e0d90
Report CID
bafkreid…b7hqua

21 findings

Each cell is one line of code. Select a cell to jump to its finding.

Rubixi.sol155 lines, 21 findings
9 uint private pyramidMultiplier = 300;
10 uint private payoutOrder = 0;
11
12 address private creator;
13
14 //Sets creator
15 function DynamicPyramid() {
16 creator = msg.sender;
17 }
18
19 modifier onlyowner {
20 if (msg.sender == creator) _;
21 }
22
23 struct Participant {
24 address etherAddress;
25 uint payout;
26 }
27
28 Participant[] private participants;
29
30 //Fallback function
31 function() {
32 init();
33 }
34
35 //init function run on fallback
36 function init() private {
37 //Ensures only tx with value of 1 ether or greater are processed and added to pyramid
38 if (msg.value < 1 ether) {
39 collectedFees += msg.value;
40 return;
41 }
42
43 uint _fee = feePercent;
44 //50% fee rebate on any ether value of 50 or greater
45 if (msg.value >= 50 ether) _fee /= 2;
46
47 addPayout(_fee);
48 }
49
50 //Function called for valid tx to the contract
51 function addPayout(uint _fee) private {
52 //Adds new address to participant array
53 participants.push(Participant(msg.sender, (msg.value * pyramidMultiplier) / 100));
54
55 //These statements ensure a quicker payout system to later pyramid entrants, so the pyramid has a longer lifespan
56 if (participants.length == 10) pyramidMultiplier = 200;
57 else if (participants.length == 25) pyramidMultiplier = 150;
58
59 // collect fees and update contract balance
60 balance += (msg.value * (100 - _fee)) / 100;
61 collectedFees += (msg.value * _fee) / 100;
62
63 //Pays earlier participiants if balance sufficient
64 while (balance > participants[payoutOrder].payout) {
65 uint payoutToSend = participants[payoutOrder].payout;
66 participants[payoutOrder].etherAddress.send(payoutToSend);
67
68 balance -= participants[payoutOrder].payout;
69 payoutOrder += 1;
70 }
71 }
72
73 //Fee functions for creator
74 function collectAllFees() onlyowner {
75 if (collectedFees == 0) throw;
76
77 creator.send(collectedFees);
78 collectedFees = 0;
79 }
80
81 function collectFeesInEther(uint _amt) onlyowner {
82 _amt *= 1 ether;
83 if (_amt > collectedFees) collectAllFees();
84
85 if (collectedFees == 0) throw;
86
87 creator.send(_amt);
88 collectedFees -= _amt;
89 }
90
91 function collectPercentOfFees(uint _pcent) onlyowner {
92 if (collectedFees == 0 || _pcent > 100) throw;
93
94 uint feesToCollect = collectedFees / 100 * _pcent;
95 creator.send(feesToCollect);
96 collectedFees -= feesToCollect;
97 }
98
99 //Functions for changing variables related to the contract
100 function changeOwner(address _owner) onlyowner {
101 creator = _owner;
102 }
103
104 function changeMultiplier(uint _mult) onlyowner {
105 if (_mult > 300 || _mult < 120) throw;
106
107 pyramidMultiplier = _mult;
108 }
109
110 function changeFeePercentage(uint _fee) onlyowner {
111 if (_fee > 10) throw;
112
113 feePercent = _fee;
114 }
115
116 //Functions to provide information to end-user using JSON interface or other interfaces
117 function currentMultiplier() constant returns(uint multiplier, string info) {
118 multiplier = pyramidMultiplier;
119 info = 'This multiplier applies to you as soon as transaction is received, may be lowered to hasten payouts or increased if payouts are fast enough. Due to no float or decimals, multiplier is x100 for a fractional multiplier e.g. 250 is actually a 2.5x multiplier. Capped at 3x max and 1.2x min.';
120 }

Signed inference receipts

Every model call is recorded with the prompt and response hashes, the provider request id and token usage, and signed by the Sentinel attester as EIP-712 data. The Merkle root of these receipts is stored onchain with the audit.

  • #0cx/gpt-5.6-terra via 9router.dea.web.id, analysis:Rubixi.solrequest resp_01dd8ffe5acf47c0016ad60618d5488193957534b68a7cb6c04,095 in, 1,514 out, 58 ssig 0x9918…8b1c
  • #1ag/claude-sonnet-4-6 via 9router.dea.web.id, quorum:F-01request chatcmpl-msg_vrtx_011CgBZNnqyMaH1F1Yhhh25J2,690 in, 102 out, 7.6 ssig 0x5ca9…f21b

Verify this report yourself

Your browser recomputes the report hash, the CID, every receipt signature and the Merkle root from the file, then reads AuditRegistry on Base Sepolia directly and compares. No Sentinel server is trusted for this.

Report JSON MarkdownThe JSON is the exact byte sequence whose keccak256 is the report hash onchain.