Skip to content

Commit 34e97de

Browse files
CoveMBericglau
andauthored
Stylus add security contract field (#564)
Co-authored-by: Eric Lau <[email protected]>
1 parent 537620a commit 34e97de

File tree

10 files changed

+146
-3
lines changed

10 files changed

+146
-3
lines changed

.changeset/fair-plums-throw.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@openzeppelin/wizard-stylus': patch
3+
---
4+
5+
Add security contact in contract info

packages/core/stylus/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"prepare": "tsc",
1818
"prepublish": "rimraf dist *.tsbuildinfo",
1919
"test": "ava",
20-
"test:watch": "ava --watch"
20+
"test:watch": "ava --watch",
21+
"test:update-snapshots": "ava --update-snapshots"
2122
},
2223
"devDependencies": {
2324
"@types/node": "^20.0.0",
@@ -28,4 +29,4 @@
2829
"typescript": "^5.0.0",
2930
"semver": "^7.6.0"
3031
}
31-
}
32+
}

packages/core/stylus/src/contract.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,22 @@ test('contract with sorted traits', t => {
7777
);
7878
t.snapshot(printContract(Foo));
7979
});
80+
81+
test('contract with documentation', t => {
82+
const Foo = new ContractBuilder('Foo');
83+
Foo.addDocumentation('Some documentation');
84+
t.snapshot(printContract(Foo));
85+
});
86+
87+
test('contract with security info', t => {
88+
const Foo = new ContractBuilder('Foo');
89+
Foo.addSecurityTag('[email protected]');
90+
t.snapshot(printContract(Foo));
91+
});
92+
93+
test('contract with security info and documentation', t => {
94+
const Foo = new ContractBuilder('Foo');
95+
Foo.addSecurityTag('[email protected]');
96+
Foo.addDocumentation('Some documentation');
97+
t.snapshot(printContract(Foo));
98+
});

packages/core/stylus/src/contract.test.ts.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,76 @@ Generated by [AVA](https://avajs.dev).
167167
fn funcSpecial() {}␊
168168
}␊
169169
`
170+
171+
## contract with documentation
172+
173+
> Snapshot 1
174+
175+
`// SPDX-License-Identifier: MIT␊
176+
// Compatible with OpenZeppelin Contracts for Stylus ^0.2.0-alpha.4␊
177+
//! Some documentation␊
178+
179+
#![cfg_attr(not(any(test, feature = "export-abi")), no_main)]␊
180+
extern crate alloc;␊
181+
182+
use stylus_sdk::prelude::*;␊
183+
184+
#[entrypoint]␊
185+
#[storage]␊
186+
struct Foo {}␊
187+
188+
#[public]␊
189+
#[inherit]␊
190+
impl Foo {}␊
191+
`
192+
193+
## contract with security info
194+
195+
> Snapshot 1
196+
197+
`// SPDX-License-Identifier: MIT␊
198+
// Compatible with OpenZeppelin Contracts for Stylus ^0.2.0-alpha.4␊
199+
200+
//! # Security␊
201+
//!␊
202+
//! For security issues, please contact: [email protected]
203+
204+
#![cfg_attr(not(any(test, feature = "export-abi")), no_main)]␊
205+
extern crate alloc;␊
206+
207+
use stylus_sdk::prelude::*;␊
208+
209+
#[entrypoint]␊
210+
#[storage]␊
211+
struct Foo {}␊
212+
213+
#[public]␊
214+
#[inherit]␊
215+
impl Foo {}␊
216+
`
217+
218+
## contract with security info and documentation
219+
220+
> Snapshot 1
221+
222+
`// SPDX-License-Identifier: MIT␊
223+
// Compatible with OpenZeppelin Contracts for Stylus ^0.2.0-alpha.4␊
224+
//! Some documentation␊
225+
226+
//! # Security␊
227+
//!␊
228+
//! For security issues, please contact: [email protected]
229+
230+
#![cfg_attr(not(any(test, feature = "export-abi")), no_main)]␊
231+
extern crate alloc;␊
232+
233+
use stylus_sdk::prelude::*;␊
234+
235+
#[entrypoint]␊
236+
#[storage]␊
237+
struct Foo {}␊
238+
239+
#[public]␊
240+
#[inherit]␊
241+
impl Foo {}␊
242+
`
117 Bytes
Binary file not shown.

packages/core/stylus/src/contract.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ type Name = {
77

88
export interface Contract {
99
license: string;
10+
securityContact: string;
1011
name: Name;
12+
documentations: string[];
1113
useClauses: UseClause[];
1214
implementedTraits: ImplementedTrait[];
1315
constants: Variable[];
@@ -73,6 +75,9 @@ export interface Argument {
7375
export class ContractBuilder implements Contract {
7476
readonly name: Name;
7577
license = 'MIT';
78+
securityContact = '';
79+
80+
readonly documentations: string[] = [];
7681

7782
private implementedTraitsMap: Map<string, ImplementedTrait> = new Map();
7883
private useClausesMap: Map<string, UseClause> = new Map();
@@ -199,4 +204,12 @@ export class ContractBuilder implements Contract {
199204
const existingFn = this.addFunction(baseTrait, fn);
200205
existingFn.attribute = attribute;
201206
}
207+
208+
addDocumentation(description: string) {
209+
this.documentations.push(description);
210+
}
211+
212+
addSecurityTag(securityContact: string) {
213+
this.securityContact = securityContact;
214+
}
202215
}

packages/core/stylus/src/print.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export function printContract(contract: Contract): string {
1616
[
1717
`// SPDX-License-Identifier: ${contract.license}`,
1818
`// Compatible with OpenZeppelin Contracts for Stylus ${compatibleContractsSemver}`,
19+
...printDocumentations(contract.documentations),
20+
...(contract.securityContact ? ['', ...printSecurityTag(contract.securityContact)] : []),
1921
],
2022
[`#![cfg_attr(not(any(test, feature = "export-abi")), no_main)]`, `extern crate alloc;`],
2123
spaceBetween(
@@ -284,3 +286,11 @@ function printArgument(arg: Argument): string {
284286
return `${arg.name}`;
285287
}
286288
}
289+
290+
function printDocumentations(documentations: string[]): string[] {
291+
return documentations.map(documentation => `//! ${documentation}`);
292+
}
293+
294+
function printSecurityTag(securityContact: string) {
295+
return ['//! # Security', '//!', `//! For security issues, please contact: ${securityContact}`];
296+
}

packages/core/stylus/src/set-info.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@ export const defaults: Info = { license: 'MIT' };
66

77
export type Info = {
88
license?: string;
9+
securityContact?: string;
910
};
1011

1112
export function setInfo(c: ContractBuilder, info: Info): void {
12-
const { license } = info;
13+
const { securityContact, license } = info;
14+
15+
if (securityContact) {
16+
c.addSecurityTag(securityContact);
17+
}
1318

1419
if (license) {
1520
c.license = license;

packages/ui/api/ai-assistant/function-definitions/stylus-shared.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ export const stylusCommonFunctionDescription = {
1313
type: 'object',
1414
description: 'Metadata about the contract and author',
1515
properties: {
16+
securityContact: {
17+
type: 'string',
18+
description:
19+
'Email where people can contact you to report security issues. Will only be visible if contract metadata is verified.',
20+
},
21+
1622
license: {
1723
type: 'string',
1824
description: 'The license used by the contract, default is "MIT"',

packages/ui/src/stylus/InfoSection.svelte

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script lang="ts">
22
import type { Info } from '@openzeppelin/wizard-stylus';
33
import { infoDefaults } from '@openzeppelin/wizard-stylus';
4+
import HelpTooltip from '../common/HelpTooltip.svelte';
45
56
export let info: Info;
67
</script>
@@ -13,6 +14,16 @@
1314
</label>
1415
</h1>
1516

17+
<label class="labeled-input">
18+
<span class="flex justify-between pr-2">
19+
Security Contact
20+
<HelpTooltip>
21+
Where people can contact you to report security issues. Will only be visible if contract metadata is verified.
22+
</HelpTooltip>
23+
</span>
24+
<input bind:value={info.securityContact} placeholder="[email protected]" />
25+
</label>
26+
1627
<label class="labeled-input">
1728
<span>License</span>
1829
<input bind:value={info.license} placeholder={infoDefaults.license} />

0 commit comments

Comments
 (0)