├── .gitattributes
├── .gitignore
├── .prettierrc
├── .solhint.json
├── .yarnrc
├── LICENSE
├── README.md
├── contracts
├── EmblemWeaver.sol
├── FieldGenerator.sol
├── FrameGenerator.sol
├── HardwareGenerator.sol
├── SVGs
│ ├── Fields
│ │ ├── FieldSVGs1.sol
│ │ ├── FieldSVGs10.sol
│ │ ├── FieldSVGs11.sol
│ │ ├── FieldSVGs12.sol
│ │ ├── FieldSVGs13.sol
│ │ ├── FieldSVGs14.sol
│ │ ├── FieldSVGs15.sol
│ │ ├── FieldSVGs16.sol
│ │ ├── FieldSVGs17.sol
│ │ ├── FieldSVGs18.sol
│ │ ├── FieldSVGs19.sol
│ │ ├── FieldSVGs2.sol
│ │ ├── FieldSVGs20.sol
│ │ ├── FieldSVGs21.sol
│ │ ├── FieldSVGs22.sol
│ │ ├── FieldSVGs23.sol
│ │ ├── FieldSVGs24.sol
│ │ ├── FieldSVGs3.sol
│ │ ├── FieldSVGs4.sol
│ │ ├── FieldSVGs5.sol
│ │ ├── FieldSVGs6.sol
│ │ ├── FieldSVGs7.sol
│ │ ├── FieldSVGs8.sol
│ │ └── FieldSVGs9.sol
│ ├── Frames
│ │ ├── FrameSVGs1.sol
│ │ └── FrameSVGs2.sol
│ ├── Hardware
│ │ ├── HardwareSVGs1.sol
│ │ ├── HardwareSVGs10.sol
│ │ ├── HardwareSVGs11.sol
│ │ ├── HardwareSVGs12.sol
│ │ ├── HardwareSVGs13.sol
│ │ ├── HardwareSVGs14.sol
│ │ ├── HardwareSVGs15.sol
│ │ ├── HardwareSVGs16.sol
│ │ ├── HardwareSVGs17.sol
│ │ ├── HardwareSVGs18.sol
│ │ ├── HardwareSVGs19.sol
│ │ ├── HardwareSVGs2.sol
│ │ ├── HardwareSVGs20.sol
│ │ ├── HardwareSVGs21.sol
│ │ ├── HardwareSVGs22.sol
│ │ ├── HardwareSVGs23.sol
│ │ ├── HardwareSVGs24.sol
│ │ ├── HardwareSVGs25.sol
│ │ ├── HardwareSVGs26.sol
│ │ ├── HardwareSVGs27.sol
│ │ ├── HardwareSVGs28.sol
│ │ ├── HardwareSVGs29.sol
│ │ ├── HardwareSVGs3.sol
│ │ ├── HardwareSVGs30.sol
│ │ ├── HardwareSVGs31.sol
│ │ ├── HardwareSVGs32.sol
│ │ ├── HardwareSVGs33.sol
│ │ ├── HardwareSVGs34.sol
│ │ ├── HardwareSVGs35.sol
│ │ ├── HardwareSVGs36.sol
│ │ ├── HardwareSVGs37.sol
│ │ ├── HardwareSVGs38.sol
│ │ ├── HardwareSVGs4.sol
│ │ ├── HardwareSVGs5.sol
│ │ ├── HardwareSVGs6.sol
│ │ ├── HardwareSVGs7.sol
│ │ ├── HardwareSVGs8.sol
│ │ └── HardwareSVGs9.sol
│ └── ShieldBadgeSVGs.sol
├── Shields.sol
├── interfaces
│ ├── ICategories.sol
│ ├── IColors.sol
│ ├── IEmblemWeaver.sol
│ ├── IFieldGenerator.sol
│ ├── IFieldSVGs.sol
│ ├── IFrameGenerator.sol
│ ├── IFrameSVGs.sol
│ ├── IHardwareGenerator.sol
│ ├── IHardwareSVGs.sol
│ ├── IShieldBadgeSVGs.sol
│ └── IShields.sol
├── libraries
│ └── HexStrings.sol
└── test
│ ├── EmblemWeaverTest.sol
│ ├── ShieldsGasTest.sol
│ ├── ShieldsTest.sol
│ ├── TestFieldGenerator.sol
│ └── TestHardwareGenerator.sol
├── deploy
├── 01_deploy_field_generator.ts
├── 02_deploy_hardware_generator.ts
├── 03_deploy_frame_generator.ts
├── 04_deploy_shieldbadgesvgs.ts
├── 05_deploy_emblem_weaver.ts
├── 06_deploy_shields.ts
└── 07_transfer_ownership.ts
├── deploySVGs
├── deployFieldSVGs.ts
├── deployedSVGs.json
└── helpers.ts
├── deployments
├── goerli
│ ├── .chainId
│ ├── BuildPassSVGs.json
│ ├── FieldGenerator.json
│ ├── FrameGenerator.json
│ ├── HardwareGenerator.json
│ ├── ShieldDescriptor.json
│ ├── Shields.json
│ └── solcInputs
│ │ ├── 0ac3b406cc563db62fbf6a074b8a54e1.json
│ │ ├── 120b7981f2664f557f778127eaf1c6ed.json
│ │ ├── 5bfe4b77149d6f73b152c3b333b753f0.json
│ │ ├── b18099829130d9e20f6eb2b1e8b44ffc.json
│ │ ├── f13209de5f6765da42f325a73fb27d59.json
│ │ └── f83fc13fabc733ee8b83028c3110d7b0.json
├── mainnet
│ ├── .chainId
│ ├── EmblemWeaver.json
│ ├── FieldGenerator.json
│ ├── FrameGenerator.json
│ ├── HardwareGenerator.json
│ ├── ShieldBadgeSVGs.json
│ ├── Shields.json
│ └── solcInputs
│ │ ├── 06c6c0124c47c1cdc59e63dde81c06b1.json
│ │ ├── 09befa56f4355a6ca3989fb006f2f0b3.json
│ │ ├── 132b2a838ee2991bd733956c8b035354.json
│ │ ├── 53fca273d67f718f5cb0758c3ff9defc.json
│ │ └── d28a8c5f5f1014153754a39e08baa75b.json
└── rinkeby
│ ├── .chainId
│ ├── BuildPassSVGs.json
│ ├── EmblemWeaver.json
│ ├── FieldGenerator.json
│ ├── FrameGenerator.json
│ ├── HardwareGenerator.json
│ ├── ShieldBadgeSVGs.json
│ ├── ShieldDescriptor.json
│ ├── Shields.json
│ └── solcInputs
│ ├── 06c6c0124c47c1cdc59e63dde81c06b1.json
│ ├── 09befa56f4355a6ca3989fb006f2f0b3.json
│ ├── 0ac3b406cc563db62fbf6a074b8a54e1.json
│ ├── 132b2a838ee2991bd733956c8b035354.json
│ ├── 32c3c77c4b2b5be30d2bd140bb4ee998.json
│ ├── 39707df8ab59bdff5775ed0c387546b7.json
│ ├── 3f384c0dfe2328302ebd4d9888e64775.json
│ ├── 53fca273d67f718f5cb0758c3ff9defc.json
│ ├── 5bfe4b77149d6f73b152c3b333b753f0.json
│ ├── 7b1bbcd7f29fa3ba20bf06fb65a1b0f9.json
│ ├── 97250a4cdb9387cee9c1bfaceb096ed2.json
│ ├── a9e7d4fcf53118db8118fcbd76e082b4.json
│ ├── b18099829130d9e20f6eb2b1e8b44ffc.json
│ ├── d28a8c5f5f1014153754a39e08baa75b.json
│ ├── d69528a4b69a6281f4bad594fdf80357.json
│ └── fe897b961f7bc28b8df8819c7790723a.json
├── fields.txt
├── hardhat.config.ts
├── package.json
├── test
├── EmblemWeaver.spec.ts
├── FieldSVGs.spec.ts
├── FrameSVGs.spec.ts
├── HardwareSVGs.spec.ts
├── Shields.spec.ts
├── __snapshots__
│ ├── EmblemWeaver.spec.ts.snap
│ ├── FieldSVGs.spec.ts.snap
│ ├── FrameSVGs.spec.ts.snap
│ ├── HardwareSVGs.spec.ts.snap
│ ├── ShieldDescriptor.spec.ts.snap
│ ├── Shields.spec.ts.snap
│ └── svgs
│ │ ├── .DS_Store
│ │ ├── fields
│ │ ├── 000_Perfect.svg
│ │ ├── 001_Per Pale.svg
│ │ ├── 002_Per Fess.svg
│ │ ├── 003_Per Bend Sinister.svg
│ │ ├── 004_Quarterly I.svg
│ │ ├── 005_Per Saltire.svg
│ │ ├── 006_Gyronny.svg
│ │ ├── 007_Per Chevron.svg
│ │ ├── 008_Per Chevron Inverted.svg
│ │ ├── 009_Per Chevron Ployé.svg
│ │ ├── 010_Per Chevron Inverted Ployé.svg
│ │ ├── 011_Per Pale Indented.svg
│ │ ├── 012_Per Pale Raguly.svg
│ │ ├── 013_Per Pale Embattled .svg
│ │ ├── 014_Per Pale Wavy.svg
│ │ ├── 015_Per Pale Rayonny.svg
│ │ ├── 016_Per Pale Nebuly.svg
│ │ ├── 017_Per Pall Nebuly II.svg
│ │ ├── 018_Per Pale Indented Pometty.svg
│ │ ├── 019_Per Fess Indented.svg
│ │ ├── 020_Per Fess Raguly.svg
│ │ ├── 021_Per Fess Embattled.svg
│ │ ├── 022_Per Fess Wavy.svg
│ │ ├── 023_Per Fess Rayonny.svg
│ │ ├── 024_Per Fess Nebuly I.svg
│ │ ├── 025_Per Fess Nebuly II.svg
│ │ ├── 026_Per Fess Indented Pometty.svg
│ │ ├── 027_Per Fess with a Left Step.svg
│ │ ├── 028_Per Fess Enarched.svg
│ │ ├── 029_Per Bend Sinister Engrailed.svg
│ │ ├── 030_Per Bend Sinister Wavy.svg
│ │ ├── 031_Per Bend Sinister Bevilled.svg
│ │ ├── 032_Quarterly Embattled.svg
│ │ ├── 033_Quarterly Arrondi.svg
│ │ ├── 034_Gyronny Arrondi of Twelve.svg
│ │ ├── 035_Gyronny From Base.svg
│ │ ├── 036_Gyronny From Chief.svg
│ │ ├── 037_Gyronny Wavy I.svg
│ │ ├── 038_Per Chevron Embattled.svg
│ │ ├── 039_Pale I.svg
│ │ ├── 040_Pale II.svg
│ │ ├── 041_Pale Engrailed.svg
│ │ ├── 042_Pale Lozengy.svg
│ │ ├── 043_Pale Nebuly.svg
│ │ ├── 044_Pale Offset.svg
│ │ ├── 045_Pale Embattled.svg
│ │ ├── 046_Pale Raguly.svg
│ │ ├── 047_Pale Wavy I.svg
│ │ ├── 048_Pale Wavy II.svg
│ │ ├── 049_Pale Bevilled.svg
│ │ ├── 050_Fess.svg
│ │ ├── 051_Fess Engrailed.svg
│ │ ├── 052_Fess Lozengy.svg
│ │ ├── 053_Fess Raguly.svg
│ │ ├── 054_Fess Wavy.svg
│ │ ├── 055_Fess Rayonny.svg
│ │ ├── 056_Bend Sinister I.svg
│ │ ├── 057_Bend Sinister II.svg
│ │ ├── 058_Bend Sinister Engrailed.svg
│ │ ├── 059_Bend Sinister Ragully.svg
│ │ ├── 060_Bend Sinister Wavy.svg
│ │ ├── 061_Bordure.svg
│ │ ├── 062_Bordure Engrailed.svg
│ │ ├── 063_Bordure Indented.svg
│ │ ├── 064_Bordure Embattled.svg
│ │ ├── 065_Bordure Wavy.svg
│ │ ├── 066_Bordure Rayonny.svg
│ │ ├── 067_Razor Bordure.svg
│ │ ├── 068_Canton.svg
│ │ ├── 069_Canton Sinister.svg
│ │ ├── 070_Chief.svg
│ │ ├── 071_Chief Engrailed.svg
│ │ ├── 072_Chief Indented.svg
│ │ ├── 073_Chief Nebuly.svg
│ │ ├── 074_Chief Embattled.svg
│ │ ├── 075_Chief Wavy.svg
│ │ ├── 076_Chief Rayonny.svg
│ │ ├── 077_Chief Triangular.svg
│ │ ├── 078_Chief Urdy.svg
│ │ ├── 079_Base.svg
│ │ ├── 080_Base Engrailed.svg
│ │ ├── 081_Base Indented.svg
│ │ ├── 082_Base Nebuly.svg
│ │ ├── 083_Base Embattled.svg
│ │ ├── 084_Base Wavy.svg
│ │ ├── 085_Base Rayonny.svg
│ │ ├── 086_Cross I.svg
│ │ ├── 087_Cross II.svg
│ │ ├── 088_Cross Engrailed.svg
│ │ ├── 089_Saltire.svg
│ │ ├── 090_Saltire Engrailed.svg
│ │ ├── 091_Chevron I.svg
│ │ ├── 092_Chevron II.svg
│ │ ├── 093_Chevron Embattled.svg
│ │ ├── 094_Chevron Inverted I.svg
│ │ ├── 095_Chevron Inverted II.svg
│ │ ├── 096_Two Bars.svg
│ │ ├── 097_Three Bars.svg
│ │ ├── 098_Four Bars.svg
│ │ ├── 099_Two Pallets.svg
│ │ ├── 100_Three Pallets.svg
│ │ ├── 101_Four Pallets.svg
│ │ ├── 102_Two Pales Engrailed.svg
│ │ ├── 103_Two Pales Nebuly.svg
│ │ ├── 104_Two Pales Wavy I.svg
│ │ ├── 105_Two Pales Wavy II.svg
│ │ ├── 106_Two Pales Dancetty.svg
│ │ ├── 107_Orle.svg
│ │ ├── 108_Orle Embattled.svg
│ │ ├── 109_Pall.svg
│ │ ├── 110_Pall Inverted.svg
│ │ ├── 111_Pile.svg
│ │ ├── 112_Pile Ployé.svg
│ │ ├── 113_Pile Inverted.svg
│ │ ├── 114_Pile Inverted Ployé.svg
│ │ ├── 115_Two Piles.svg
│ │ ├── 116_Flaunches.svg
│ │ ├── 117_Gyron.svg
│ │ ├── 118_Chief Pale.svg
│ │ ├── 119_Tierce.svg
│ │ ├── 120_Tierce Sinister.svg
│ │ ├── 121_Tierces.svg
│ │ ├── 122_Gore.svg
│ │ ├── 123_Gore Sinister.svg
│ │ ├── 124_Gores.svg
│ │ ├── 125_Paly of Four.svg
│ │ ├── 126_Paly of Eight.svg
│ │ ├── 127_Paly Dancetty.svg
│ │ ├── 128_Paly Embattled.svg
│ │ ├── 129_Paly Wavy I.svg
│ │ ├── 130_Paly Wavy II.svg
│ │ ├── 131_Barry of Four.svg
│ │ ├── 132_Barry of Eight.svg
│ │ ├── 133_Barry Dancetty.svg
│ │ ├── 134_Barry Embattled.svg
│ │ ├── 135_Barry Wavy I.svg
│ │ ├── 136_Barry Wavy II.svg
│ │ ├── 137_Checky I.svg
│ │ ├── 138_Checky II.svg
│ │ ├── 139_Checky III.svg
│ │ ├── 140_Checky IV.svg
│ │ ├── 141_Checky V.svg
│ │ ├── 142_Bendy Sinister I.svg
│ │ ├── 143_Bendy Sinister II.svg
│ │ ├── 144_Bendy Sinister III.svg
│ │ ├── 145_Bendy Sinister IV.svg
│ │ ├── 146_Chevronny I.svg
│ │ ├── 147_Chevronny II.svg
│ │ ├── 148_Chevronny Inverted I.svg
│ │ ├── 149_Chevronny Inverted II.svg
│ │ ├── 150_Lozengy I.svg
│ │ ├── 151_Lozengy II.svg
│ │ ├── 152_Lozengy Wide.svg
│ │ ├── 153_Lozengy Barry.svg
│ │ ├── 154_Fusilly I.svg
│ │ ├── 155_Fusilly II.svg
│ │ ├── 156_Fusilly III.svg
│ │ ├── 157_Pily I.svg
│ │ ├── 158_Pily II.svg
│ │ ├── 159_Orly.svg
│ │ ├── 160_Roundel.svg
│ │ ├── 161_Annulet.svg
│ │ ├── 162_Billet.svg
│ │ ├── 163_Triangle.svg
│ │ ├── 164_Inescutcheon.svg
│ │ ├── 165_Lozenge.svg
│ │ ├── 166_Mascle.svg
│ │ ├── 167_Mullet.svg
│ │ ├── 168_Quatrefoil.svg
│ │ ├── 169_Quasar.svg
│ │ ├── 170_Three Roundels.svg
│ │ ├── 171_Three Quatrefoils.svg
│ │ ├── 172_Semy of Roundels.svg
│ │ ├── 173_Biletty.svg
│ │ ├── 174_Semy of Quatrefoils.svg
│ │ ├── 175_Semy-de-Lis.svg
│ │ ├── 176_Estencelly.svg
│ │ ├── 177_Mullety.svg
│ │ ├── 178_Papellony.svg
│ │ ├── 179_Masoned.svg
│ │ ├── 180_Fretty I.svg
│ │ ├── 181_Fretty II.svg
│ │ ├── 182_Grillage.svg
│ │ ├── 183_Vair.svg
│ │ ├── 184_Counter-Vair.svg
│ │ ├── 185_Vair Ancient.svg
│ │ ├── 186_Per Pale and Per Chevron.svg
│ │ ├── 187_Per Pale and Per Fess Indented.svg
│ │ ├── 188_Per Fess and Per Pale Wavy.svg
│ │ ├── 189_Per Saltire and Per Fess.svg
│ │ ├── 190_Per Pale and Barry of Four.svg
│ │ ├── 191_Per Pale and Barry of Eight.svg
│ │ ├── 192_Per Fess and Paly of Five.svg
│ │ ├── 193_Per Fess and Two Pallets.svg
│ │ ├── 194_Cross and Saltire I.svg
│ │ ├── 195_Grid.svg
│ │ ├── 196_Supergrid I.svg
│ │ ├── 197_Supergrid II.svg
│ │ ├── 198_Microdot.svg
│ │ ├── 199_Ehrenstein.svg
│ │ ├── 200_Semy of Alternating Roundels.svg
│ │ ├── 201_Quasar Semy.svg
│ │ ├── 202_Tiles V.svg
│ │ ├── 203_QuiltX I.svg
│ │ ├── 204_Bloomy.svg
│ │ ├── 205_Talon Matrix I.svg
│ │ ├── 206_Doppler.svg
│ │ ├── 207_Nine Rings.svg
│ │ ├── 208_Ripple.svg
│ │ ├── 209_Spiral.svg
│ │ ├── 210_Rasterwave Pallets.svg
│ │ ├── 211_Rasterlines Barry.svg
│ │ ├── 212_Rasterlines Bend Sinister.svg
│ │ ├── 213_Rasterlines Pale Horizon.svg
│ │ ├── 214_Rasterlines Barry and Bendy Sinister.svg
│ │ ├── 215_Rasterlines Barry-X.svg
│ │ ├── 216_Gyronny Wavy II.svg
│ │ ├── 217_Hypno.svg
│ │ ├── 218_Infinigyron.svg
│ │ ├── 219_Laser.svg
│ │ ├── 220_Laser and Boxes Countercharged.svg
│ │ ├── 221_Quadrobeams.svg
│ │ ├── 222_Laserwheels.svg
│ │ ├── 223_Gyronny and Orly.svg
│ │ ├── 224_Flex Checky.svg
│ │ ├── 225_Hyperbend.svg
│ │ ├── 226_Burst.svg
│ │ ├── 227_Shattered.svg
│ │ ├── 228_Warp.svg
│ │ ├── 229_Mach.svg
│ │ ├── 230_Kaleidoscope.svg
│ │ ├── 231_AxoPile.svg
│ │ ├── 232_Lens.svg
│ │ ├── 233_Bender.svg
│ │ ├── 234_Stretcher.svg
│ │ ├── 235_Inner Sphere.svg
│ │ ├── 236_Stepper.svg
│ │ ├── 237_Per Bend Sinister Hand.svg
│ │ ├── 238_Per Pale Indented Hand.svg
│ │ ├── 239_Pall Inverted Hand.svg
│ │ ├── 240_Orle Hand.svg
│ │ ├── 241_Five Pallets Hand.svg
│ │ ├── 242_Per Pall.svg
│ │ ├── 243_Per Pall Inverted.svg
│ │ ├── 244_Tierced Per Pale.svg
│ │ ├── 245_Tierced per Fess.svg
│ │ ├── 246_Tierced per Bend Sinister.svg
│ │ ├── 247_Tierced Per Pale and Per Fess I.svg
│ │ ├── 248_Tierced Per Pale and Per Fess II.svg
│ │ ├── 249_Pale Checky.svg
│ │ ├── 250_Bordure Compony.svg
│ │ ├── 251_Bordure Parted Bordurewise.svg
│ │ ├── 252_Bordure Counter-Compony.svg
│ │ ├── 253_Cross Cotised.svg
│ │ ├── 254_Saltire Cotised.svg
│ │ ├── 255_Orle on a Bordure.svg
│ │ ├── 256_Pall Cotised.svg
│ │ ├── 257_Pall Inverted Cotised.svg
│ │ ├── 258_Fretty Parted.svg
│ │ ├── 259_Party of Eight.svg
│ │ ├── 260_Three Quatrefoils on a Chief.svg
│ │ ├── 261_Cross on a Chief.svg
│ │ ├── 262_Saltire on a Chief.svg
│ │ ├── 263_Rising Sun on a Chief.svg
│ │ ├── 264_Tierces and Three Quatrefoils.svg
│ │ ├── 265_Three Quatrefoils on a Bend.svg
│ │ ├── 266_Saltire on a Canton.svg
│ │ ├── 267_Gyronny Saltire.svg
│ │ ├── 268_Eight-pointed Star on a Cross and Saltire Engrailed.svg
│ │ ├── 269_Cross and Saltire II.svg
│ │ ├── 270_Saltire Engrailed on a Saltire.svg
│ │ ├── 271_Per Saltire and a Saltire.svg
│ │ ├── 272_Quarterly, Perfect and Quarterly.svg
│ │ ├── 273_Quarterly, Perfect and Check.svg
│ │ ├── 274_Quarterly, Perfect and a Bend Sinister.svg
│ │ ├── 275_Quarterly, Perfect and Per Bend Sinister.svg
│ │ ├── 276_Quarterly, Perfect and a Saltire.svg
│ │ ├── 277_Per Pale, Perfect and Barry of Eight.svg
│ │ ├── 278_Per Pale, Semy of Ten Four-pointed Stars and Barry of Eight.svg
│ │ ├── 279_Per Pale, Paly of Eight and Perfect.svg
│ │ ├── 280_Semy of Sixteen Quatrefoils and a Chief.svg
│ │ ├── 281_Semy of Eighteen Four-pointed Stars and a Base.svg
│ │ ├── 282_Fixture.svg
│ │ ├── 283_Net.svg
│ │ ├── 284_Reticle.svg
│ │ ├── 285_Sparkle.svg
│ │ ├── 286_Talon Matrix II.svg
│ │ ├── 287_Tiles I.svg
│ │ ├── 288_Tiles IV.svg
│ │ ├── 289_Xanom.svg
│ │ ├── 290_QuiltX II.svg
│ │ ├── 291_Cubey I.svg
│ │ ├── 292_Cubey II.svg
│ │ ├── 293_Quarterly II.svg
│ │ ├── 294_Quarterly, a Cross and a Bar.svg
│ │ ├── 295_Per Pall Inverted and a Chief.svg
│ │ ├── 296_Per Pall Inverted and Chevronelly.svg
│ │ ├── 297_Check.svg
│ │ ├── 298_Tiles II.svg
│ │ └── 299_Tiles III.svg
│ │ ├── frame.svg
│ │ ├── frames
│ │ ├── 000_.svg
│ │ ├── 001_Adorned.svg
│ │ ├── 002_Menacing.svg
│ │ ├── 003_Secured.svg
│ │ ├── 004_Floriated.svg
│ │ └── 005_Everlasting.svg
│ │ ├── hardware.svg
│ │ └── hardware
│ │ ├── 000_Bushing Hammer.svg
│ │ ├── 001_Shovel.svg
│ │ ├── 002_Screw.svg
│ │ ├── 003_Flathead Screwdriver.svg
│ │ ├── 004_Pen Nib.svg
│ │ ├── 005_Scissors.svg
│ │ ├── 006_Compass.svg
│ │ ├── 007_Gear.svg
│ │ ├── 008_Tongs.svg
│ │ ├── 009_Compass and Triangle.svg
│ │ ├── 010_Magnifying Glass.svg
│ │ ├── 011_Shears.svg
│ │ ├── 012_End Cutting Pliers.svg
│ │ ├── 013_Wheel.svg
│ │ ├── 014_Tuning Fork.svg
│ │ ├── 015_Mallet with Chisels in Saltire.svg
│ │ ├── 016_Hammer and Compass.svg
│ │ ├── 017_Spring Caliper.svg
│ │ ├── 018_Book.svg
│ │ ├── 019_Calipers.svg
│ │ ├── 020_Three Nails.svg
│ │ ├── 021_Awl.svg
│ │ ├── 022_French Key Wrench.svg
│ │ ├── 023_Pocketwatch.svg
│ │ ├── 024_Anvil.svg
│ │ ├── 025_Crozier.svg
│ │ ├── 026_Jackhammer.svg
│ │ ├── 027_Jewelers Loupe.svg
│ │ ├── 028_Fasces.svg
│ │ ├── 029_Cauldron.svg
│ │ ├── 030_Horseshoe and Star.svg
│ │ ├── 031_Lug Wrench and Four Lug Nuts.svg
│ │ ├── 032_Masonry Trowel and Brickwork.svg
│ │ ├── 033_Rudder.svg
│ │ ├── 034_Gavel.svg
│ │ ├── 035_Tongs and Hammer.svg
│ │ ├── 036_Pen Tool.svg
│ │ ├── 037_Triskele Tracery.svg
│ │ ├── 037_Triskele.svg
│ │ ├── 038_Quatrefoil and Three Books in Chief.svg
│ │ ├── 039_Keyhole.svg
│ │ ├── 040_Pitcher.svg
│ │ ├── 041_Piston.svg
│ │ ├── 042_Scales.svg
│ │ ├── 043_Pulleys.svg
│ │ ├── 044_Gears.svg
│ │ ├── 045_Astrolabe.svg
│ │ ├── 046_Laser Level.svg
│ │ ├── 047_Wheatstalk and Two Suns.svg
│ │ ├── 048_Shipwheel.svg
│ │ ├── 049_Pipe Organ.svg
│ │ ├── 050_Knight.svg
│ │ ├── 051_Garb.svg
│ │ ├── 052_Anchor.svg
│ │ ├── 053_Bells.svg
│ │ ├── 054_Stack.svg
│ │ ├── 055_Orb.svg
│ │ ├── 056_Command in Canton.svg
│ │ ├── 057_Three Chalices.svg
│ │ ├── 058_Three Brushes.svg
│ │ ├── 059_Three Writing Pens.svg
│ │ ├── 060_Lead Holder and Twin Blades.svg
│ │ ├── 061_Scyths Saltire and Treestump.svg
│ │ ├── 062_Mining Helmet and Picks Saltire.svg
│ │ ├── 063_Flower Pot.svg
│ │ ├── 064_Pickaxes.svg
│ │ ├── 065_Three Bells in Chief.svg
│ │ ├── 066_Three Suns in Chief.svg
│ │ ├── 067_Quatrefoil Tracery in Chief.svg
│ │ ├── 068_Two Suns.svg
│ │ ├── 069_Four Suns.svg
│ │ ├── 070_Two Books.svg
│ │ ├── 071_Orle of Chains.svg
│ │ ├── 072_Crancelin.svg
│ │ ├── 073_Four Wheels.svg
│ │ ├── 074_Pear Diamond.svg
│ │ ├── 075_Maple Leaf.svg
│ │ ├── 076_Eighteen Orbs and Crown in Chief.svg
│ │ ├── 077_Croziers in Saltire and Star.svg
│ │ ├── 077_Croziers in Saltire and Stars.svg
│ │ ├── 078_Plough and Sun In Splendour.svg
│ │ ├── 079_Telescope and Stars.svg
│ │ ├── 080_Necklace.svg
│ │ ├── 081_Pillar and Twin Quatrefoils.svg
│ │ ├── 082_Horse-head Gables.svg
│ │ ├── 083_Sextant.svg
│ │ ├── 084_Lyre.svg
│ │ ├── 085_Eye of Providence.svg
│ │ ├── 086_Clockwork.svg
│ │ ├── 087_Castle.svg
│ │ ├── 088_Needle and Thread.svg
│ │ ├── 089_Portcullis.svg
│ │ ├── 090_Tree.svg
│ │ ├── 091_Pugin Thistle.svg
│ │ ├── 092_Gauntlet.svg
│ │ ├── 093_Two Fleury Hinges Issuant from Dexter.svg
│ │ ├── 094_Torch.svg
│ │ ├── 095_Sun and Moon.svg
│ │ ├── 096_Helm of the Esquire.svg
│ │ ├── 097_Helm of the Knight.svg
│ │ ├── 098_Helm of the Monarch.svg
│ │ ├── 099_Vambraced Arm of the Warrior.svg
│ │ ├── 100_Vambraced Arm of the Mage.svg
│ │ ├── 101_Vambraced Arm of the Hunter.svg
│ │ ├── 102_Palace Key.svg
│ │ ├── 103_Vault Key.svg
│ │ ├── 104_Dungeon Key.svg
│ │ ├── 105_Chain Palewise.svg
│ │ ├── 106_Cross Saltire and Orle of Chains.svg
│ │ ├── 107_Chain Maille.svg
│ │ ├── 108_Trypto Plate.svg
│ │ ├── 109_Bordure Plate.svg
│ │ ├── 110_Inverted Pall Plate.svg
│ │ ├── 111_Escarbuncle.svg
│ │ ├── 112_Tracery.svg
│ │ ├── 113_Starfield.svg
│ │ ├── 114_Wings.svg
│ │ ├── 115_Skull.svg
│ │ ├── 116_Rose.svg
│ │ ├── 117_Shields Plate.svg
│ │ ├── 118_Shields Bracket.svg
│ │ ├── 119_The Book of Shields.svg
│ │ └── 120_Three Shields.svg
└── shared
│ ├── buildShield.ts
│ ├── colors.ts
│ ├── deployFieldGenerator.ts
│ ├── deployFrameGenerator.ts
│ ├── deployHardwareGenerator.ts
│ ├── deployTestFieldGenerator.ts
│ ├── deployTestHardwareGenerator.ts
│ ├── encodeColors.ts
│ ├── expect.ts
│ ├── extractJSONFromURI.ts
│ ├── printSVGToSnapshots.ts
│ └── snapshotGasCost.ts
├── tsconfig.json
└── yarn.lock
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.sol linguist-language=Solidity
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | artifacts/
2 | cache/
3 | crytic-export/
4 | node_modules/
5 | typechain/
6 | .env
7 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true,
4 | "printWidth": 120
5 | }
6 |
--------------------------------------------------------------------------------
/.solhint.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["prettier"],
3 | "rules": {
4 | "prettier/prettier": "error"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.yarnrc:
--------------------------------------------------------------------------------
1 | ignore-scripts true
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Shields
2 |
3 | Main repo for the Shields smart contracts.
4 |
5 | ## Deployment Addresses
6 | | Contract | Address | Source Code |
7 | | ---------------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
8 | | Shields | `0x0747118C9F44C7a23365b2476dCD05E03114C747` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/Shields.sol |
9 | | EmblemWeaver | `0x3E2063199F7b98b8188B7649d95bd0C82f4B0001` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/EmblemWeaver.sol |
10 | | FieldGenerator | `0x0230eB753Df1A12063B357EB5e3A4F9Ce0780C1F` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/FieldGenerator.sol |
11 | | HardwareGenerator | `0x355944B17A0770190eCB375ec3E64b98Cb31a576` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/HardwareGenerator.sol |
12 | | FrameGenerator | `0x3b6cdEC2F91F4C7780C966B7Bfc6a8f55083863e` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/FrameGenerator.sol |
13 | | ShieldBadgeSVGs | `0xCCAc9aB49b53B7c228C47C55ac8B5704cFc57997` | https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/contracts/SVGs/ShieldBadgeSVGs.sol |
14 |
15 | All crest SVG addresses are listed in [deployedSVGs.json](https://github.com/johncpalmer/ugp-crest-contracts/blob/aa7e312c20a8cb2526881a4436df4869fd0d87a7/deploySVGs/deployedSVGs.json).
16 |
17 | ## Setup Instructions
18 |
19 | Must be running `node v14` or later.
20 |
21 | ### Testing
22 |
23 | First make sure you have run `yarn install` and `yarn run build`.
24 |
25 | ```
26 | yarn run test
27 | ```
28 |
29 | to update snapshots:
30 | ```
31 | UPDATE_SNAPSHOT=1 yarn test
32 | ```
33 |
--------------------------------------------------------------------------------
/contracts/FrameGenerator.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import './interfaces/IFrameGenerator.sol';
5 | import './interfaces/IFrameSVGs.sol';
6 | import '@openzeppelin/contracts/utils/Strings.sol';
7 |
8 | /// @dev Generate Frame SVG and properties
9 | contract FrameGenerator is IFrameGenerator {
10 | using Strings for uint16;
11 |
12 | IFrameSVGs immutable frameSVGs1;
13 | IFrameSVGs immutable frameSVGs2;
14 |
15 | constructor(FrameSVGs memory svgs) {
16 | frameSVGs1 = svgs.frameSVGs1;
17 | frameSVGs2 = svgs.frameSVGs2;
18 | }
19 |
20 | function generateFrame(uint16 frame) external view override returns (IFrameSVGs.FrameData memory) {
21 | if (frame <= 3) {
22 | return callFrameSVGs(frameSVGs1, frame);
23 | }
24 |
25 | if (frame <= 5) {
26 | return callFrameSVGs(frameSVGs2, frame);
27 | }
28 |
29 | revert('invalid frame selection');
30 | }
31 |
32 | function callFrameSVGs(IFrameSVGs target, uint16 frame) internal view returns (IFrameSVGs.FrameData memory) {
33 | bytes memory functionSelector = abi.encodePacked('frame_', uint16(frame).toString(), '()');
34 |
35 | bool success;
36 | bytes memory result;
37 | (success, result) = address(target).staticcall(abi.encodeWithSelector(bytes4(keccak256(functionSelector))));
38 |
39 | return abi.decode(result, (IFrameSVGs.FrameData));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/contracts/interfaces/ICategories.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | interface ICategories {
5 | enum FieldCategories {
6 | MYTHIC,
7 | HERALDIC
8 | }
9 |
10 | enum HardwareCategories {
11 | STANDARD,
12 | SPECIAL
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/contracts/interfaces/IColors.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | interface IColors {
5 | event ColorAdded(uint24 color, string title);
6 |
7 | struct Color {
8 | string title;
9 | bool exists;
10 | }
11 |
12 | /// @notice Returns true if color exists in contract, else false.
13 | /// @param color 3-byte uint representing color
14 | /// @return true or false
15 | function colorExists(uint24 color) external view returns (bool);
16 |
17 | /// @notice Returns the title string corresponding to the 3-byte color
18 | /// @param color 3-byte uint representing color
19 | /// @return true or false
20 | function colorTitle(uint24 color) external view returns (string memory);
21 | }
22 |
--------------------------------------------------------------------------------
/contracts/interfaces/IEmblemWeaver.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import './IShields.sol';
5 | import './IFrameGenerator.sol';
6 | import './IFieldGenerator.sol';
7 | import './IHardwareGenerator.sol';
8 |
9 | /// @dev Generate Customizable Shields
10 | interface IEmblemWeaver {
11 | function fieldGenerator() external returns (IFieldGenerator);
12 |
13 | function hardwareGenerator() external returns (IHardwareGenerator);
14 |
15 | function frameGenerator() external returns (IFrameGenerator);
16 |
17 | function generateShieldURI(IShields.Shield memory shield) external view returns (string memory);
18 |
19 | function generateShieldBadgeURI(IShields.ShieldBadge shieldBadge) external view returns (string memory);
20 | }
21 |
--------------------------------------------------------------------------------
/contracts/interfaces/IFieldGenerator.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import './IFieldSVGs.sol';
5 | import './IColors.sol';
6 |
7 | /// @dev Generate Field SVG
8 | interface IFieldGenerator {
9 | /// @param field uint representing field selection
10 | /// @param colors to be rendered in the field svg
11 | /// @return FieldData containing svg snippet and field title
12 | function generateField(uint16 field, uint24[4] memory colors) external view returns (IFieldSVGs.FieldData memory);
13 |
14 | event ColorAdded(uint24 color, string title);
15 |
16 | struct Color {
17 | string title;
18 | bool exists;
19 | }
20 |
21 | /// @notice Returns true if color exists in contract, else false.
22 | /// @param color 3-byte uint representing color
23 | /// @return true or false
24 | function colorExists(uint24 color) external view returns (bool);
25 |
26 | /// @notice Returns the title string corresponding to the 3-byte color
27 | /// @param color 3-byte uint representing color
28 | /// @return true or false
29 | function colorTitle(uint24 color) external view returns (string memory);
30 |
31 | struct FieldSVGs {
32 | IFieldSVGs fieldSVGs1;
33 | IFieldSVGs fieldSVGs2;
34 | IFieldSVGs fieldSVGs3;
35 | IFieldSVGs fieldSVGs4;
36 | IFieldSVGs fieldSVGs5;
37 | IFieldSVGs fieldSVGs6;
38 | IFieldSVGs fieldSVGs7;
39 | IFieldSVGs fieldSVGs8;
40 | IFieldSVGs fieldSVGs9;
41 | IFieldSVGs fieldSVGs10;
42 | IFieldSVGs fieldSVGs11;
43 | IFieldSVGs fieldSVGs12;
44 | IFieldSVGs fieldSVGs13;
45 | IFieldSVGs fieldSVGs14;
46 | IFieldSVGs fieldSVGs15;
47 | IFieldSVGs fieldSVGs16;
48 | IFieldSVGs fieldSVGs17;
49 | IFieldSVGs fieldSVGs18;
50 | IFieldSVGs fieldSVGs19;
51 | IFieldSVGs fieldSVGs20;
52 | IFieldSVGs fieldSVGs21;
53 | IFieldSVGs fieldSVGs22;
54 | IFieldSVGs fieldSVGs23;
55 | IFieldSVGs fieldSVGs24;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/contracts/interfaces/IFieldSVGs.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import './ICategories.sol';
5 |
6 | interface IFieldSVGs {
7 | struct FieldData {
8 | string title;
9 | ICategories.FieldCategories fieldType;
10 | string svgString;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/contracts/interfaces/IFrameGenerator.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import './IFrameSVGs.sol';
5 |
6 | /// @dev Generate Frame SVG
7 | interface IFrameGenerator {
8 | struct FrameSVGs {
9 | IFrameSVGs frameSVGs1;
10 | IFrameSVGs frameSVGs2;
11 | }
12 |
13 | /// @param Frame uint representing Frame selection
14 | /// @return FrameData containing svg snippet and Frame title and Frame type
15 | function generateFrame(uint16 Frame) external view returns (IFrameSVGs.FrameData memory);
16 | }
17 |
--------------------------------------------------------------------------------
/contracts/interfaces/IFrameSVGs.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | interface IFrameSVGs {
5 | struct FrameData {
6 | string title;
7 | uint256 fee;
8 | string svgString;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/contracts/interfaces/IHardwareGenerator.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import './IHardwareSVGs.sol';
5 |
6 | /// @dev Generate Hardware SVG
7 | interface IHardwareGenerator {
8 |
9 | /// @param hardware uint representing hardware selection
10 | /// @return HardwareData containing svg snippet and hardware title and hardware type
11 | function generateHardware(uint16 hardware) external view returns (IHardwareSVGs.HardwareData memory);
12 |
13 | struct HardwareSVGs {
14 | IHardwareSVGs hardwareSVGs1;
15 | IHardwareSVGs hardwareSVGs2;
16 | IHardwareSVGs hardwareSVGs3;
17 | IHardwareSVGs hardwareSVGs4;
18 | IHardwareSVGs hardwareSVGs5;
19 | IHardwareSVGs hardwareSVGs6;
20 | IHardwareSVGs hardwareSVGs7;
21 | IHardwareSVGs hardwareSVGs8;
22 | IHardwareSVGs hardwareSVGs9;
23 | IHardwareSVGs hardwareSVGs10;
24 | IHardwareSVGs hardwareSVGs11;
25 | IHardwareSVGs hardwareSVGs12;
26 | IHardwareSVGs hardwareSVGs13;
27 | IHardwareSVGs hardwareSVGs14;
28 | IHardwareSVGs hardwareSVGs15;
29 | IHardwareSVGs hardwareSVGs16;
30 | IHardwareSVGs hardwareSVGs17;
31 | IHardwareSVGs hardwareSVGs18;
32 | IHardwareSVGs hardwareSVGs19;
33 | IHardwareSVGs hardwareSVGs20;
34 | IHardwareSVGs hardwareSVGs21;
35 | IHardwareSVGs hardwareSVGs22;
36 | IHardwareSVGs hardwareSVGs23;
37 | IHardwareSVGs hardwareSVGs24;
38 | IHardwareSVGs hardwareSVGs25;
39 | IHardwareSVGs hardwareSVGs26;
40 | IHardwareSVGs hardwareSVGs27;
41 | IHardwareSVGs hardwareSVGs28;
42 | IHardwareSVGs hardwareSVGs29;
43 | IHardwareSVGs hardwareSVGs30;
44 | IHardwareSVGs hardwareSVGs31;
45 | IHardwareSVGs hardwareSVGs32;
46 | IHardwareSVGs hardwareSVGs33;
47 | IHardwareSVGs hardwareSVGs34;
48 | IHardwareSVGs hardwareSVGs35;
49 | IHardwareSVGs hardwareSVGs36;
50 | IHardwareSVGs hardwareSVGs37;
51 | IHardwareSVGs hardwareSVGs38;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/contracts/interfaces/IHardwareSVGs.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import './ICategories.sol';
5 |
6 | interface IHardwareSVGs {
7 | struct HardwareData {
8 | string title;
9 | ICategories.HardwareCategories hardwareType;
10 | string svgString;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/contracts/interfaces/IShieldBadgeSVGs.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import './IShields.sol';
5 |
6 | /// @dev Generate ShieldBadge SVG
7 | interface IShieldBadgeSVGs {
8 | function generateShieldBadgeSVG(IShields.ShieldBadge shieldBadge) external view returns (string memory);
9 | }
10 |
--------------------------------------------------------------------------------
/contracts/interfaces/IShields.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
5 | import '@openzeppelin/contracts/access/Ownable.sol';
6 | import '@openzeppelin/contracts/utils/Strings.sol';
7 |
8 | /// @dev Build Customizable Shields for an NFT
9 | interface IShields is IERC721 {
10 | enum ShieldBadge {
11 | MAKER,
12 | STANDARD
13 | }
14 |
15 | struct Shield {
16 | bool built;
17 | uint16 field;
18 | uint16 hardware;
19 | uint16 frame;
20 | ShieldBadge shieldBadge;
21 | uint24[4] colors;
22 | }
23 |
24 | function build(
25 | uint16 field,
26 | uint16 hardware,
27 | uint16 frame,
28 | uint24[4] memory colors,
29 | uint256 tokenId
30 | ) external payable;
31 |
32 | function shields(uint256 tokenId)
33 | external
34 | view
35 | returns (
36 | uint16 field,
37 | uint16 hardware,
38 | uint16 frame,
39 | uint24 color1,
40 | uint24 color2,
41 | uint24 color3,
42 | uint24 color4,
43 | ShieldBadge shieldBadge
44 | );
45 | }
46 |
--------------------------------------------------------------------------------
/contracts/libraries/HexStrings.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.9;
3 |
4 | library HexStrings {
5 | bytes16 internal constant ALPHABET = '0123456789abcdef';
6 |
7 | function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory) {
8 | bytes memory buffer = new bytes(2 * length);
9 | for (uint256 i = buffer.length; i > 0; i--) {
10 | buffer[i - 1] = ALPHABET[value & 0xf];
11 | value >>= 4;
12 | }
13 | return string(buffer);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/contracts/test/EmblemWeaverTest.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import '../interfaces/IShields.sol';
5 | import '../interfaces/IFrameGenerator.sol';
6 | import '../interfaces/IFieldGenerator.sol';
7 | import '../interfaces/IHardwareGenerator.sol';
8 | import '../EmblemWeaver.sol';
9 |
10 | /// @dev Generate Shield Metadata
11 | contract EmblemWeaverTest is EmblemWeaver {
12 | constructor(
13 | IFieldGenerator _fieldGenerator,
14 | IHardwareGenerator _hardwareGenerator,
15 | IFrameGenerator _frameGenerator,
16 | IShieldBadgeSVGs _shieldBadgeSVGGenerator
17 | ) EmblemWeaver(_fieldGenerator, _hardwareGenerator, _frameGenerator, _shieldBadgeSVGGenerator) {}
18 |
19 | function generateSVGTest(IShields.Shield memory shield)
20 | external
21 | view
22 | returns (
23 | string memory svg,
24 | string memory fieldTitle,
25 | string memory hardwareTitle,
26 | string memory frameTitle
27 | )
28 | {
29 | IFieldSVGs.FieldData memory field = fieldGenerator.generateField(shield.field, shield.colors);
30 | IHardwareSVGs.HardwareData memory hardware = hardwareGenerator.generateHardware(shield.hardware);
31 | IFrameSVGs.FrameData memory frame = frameGenerator.generateFrame(shield.frame);
32 |
33 | svg = string(generateSVG(field.svgString, hardware.svgString, frame.svgString));
34 | fieldTitle = field.title;
35 | hardwareTitle = hardware.title;
36 | frameTitle = frame.title;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/contracts/test/ShieldsGasTest.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import '../Shields.sol';
5 |
6 | /// @dev Generate Customizable Shields
7 | contract ShieldsGasTest {
8 | Shields public immutable shields;
9 |
10 | constructor(Shields _shields) {
11 | shields = _shields;
12 | }
13 |
14 | function gasSnapshotTokenURI(uint256 tokenId) public view returns (uint256) {
15 | uint256 gasBefore = gasleft();
16 | shields.tokenURI(tokenId);
17 | return gasBefore - gasleft();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/contracts/test/ShieldsTest.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import '../Shields.sol';
5 | import '../interfaces/IFieldSVGs.sol';
6 | import '../interfaces/IHardwareSVGs.sol';
7 | import '../interfaces/IFrameSVGs.sol';
8 | import '../interfaces/IShieldBadgeSVGs.sol';
9 |
10 | /// @dev Generate Customizable Shields
11 | contract ShieldsTest is Shields {
12 | constructor(
13 | string memory name_,
14 | string memory symbol_,
15 | IEmblemWeaver _emblemWeaver,
16 | address _makerBadgeRecipient,
17 | address _granteeBadgeRecipient
18 | ) Shields(name_, symbol_, _emblemWeaver, _makerBadgeRecipient, _granteeBadgeRecipient) {}
19 |
20 | function getNextId() external view returns (uint256) {
21 | return _nextId;
22 | }
23 |
24 | function setNextId(uint256 nextId) external {
25 | _nextId = nextId;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/contracts/test/TestFieldGenerator.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import '../interfaces/IFieldGenerator.sol';
5 | import '../interfaces/IFieldSVGs.sol';
6 | import '@openzeppelin/contracts/utils/Strings.sol';
7 |
8 | /// @dev Test Field Generator with less SVGs / less deploy overhead
9 | contract TestFieldGenerator is IFieldGenerator {
10 | using Strings for uint16;
11 |
12 | mapping(uint24 => Color) public _colors;
13 |
14 | struct TestFieldSVGs {
15 | IFieldSVGs fieldSVGs1;
16 | IFieldSVGs fieldSVGs2;
17 | }
18 |
19 | IFieldSVGs immutable fieldSVGs1;
20 | IFieldSVGs immutable fieldSVGs2;
21 |
22 | constructor(
23 | uint24[] memory __colors,
24 | string[] memory titles,
25 | TestFieldSVGs memory svgs
26 | ) {
27 | require(__colors.length == titles.length, 'invalid array lengths');
28 | for (uint256 i = 0; i < __colors.length; i++) {
29 | _colors[__colors[i]] = Color({title: titles[i], exists: true});
30 | emit ColorAdded(__colors[i], titles[i]);
31 | }
32 |
33 | fieldSVGs1 = svgs.fieldSVGs1;
34 | fieldSVGs2 = svgs.fieldSVGs2;
35 | }
36 |
37 | function colorExists(uint24 color) public view override returns (bool) {
38 | return _colors[color].exists;
39 | }
40 |
41 | function colorTitle(uint24 color) public view override returns (string memory) {
42 | return _colors[color].title;
43 | }
44 |
45 | function callFieldSVGs(
46 | IFieldSVGs target,
47 | uint16 field,
48 | uint24[4] memory colors
49 | ) internal view returns (IFieldSVGs.FieldData memory) {
50 | bytes memory functionSelector = abi.encodePacked('field_', uint16(field).toString(), '(uint24[4])');
51 |
52 | bool success;
53 | bytes memory result;
54 | (success, result) = address(target).staticcall(
55 | abi.encodeWithSelector(bytes4(keccak256(functionSelector)), colors)
56 | );
57 |
58 | return abi.decode(result, (IFieldSVGs.FieldData));
59 | }
60 |
61 | function generateField(uint16 field, uint24[4] memory colors)
62 | external
63 | view
64 | override
65 | returns (IFieldSVGs.FieldData memory)
66 | {
67 | if (field <= 28) {
68 | return callFieldSVGs(fieldSVGs1, field, colors);
69 | }
70 |
71 | if (field <= 50) {
72 | return callFieldSVGs(fieldSVGs2, field, colors);
73 | }
74 | revert('invalid field selection');
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/contracts/test/TestHardwareGenerator.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: The Unlicense
2 | pragma solidity ^0.8.9;
3 |
4 | import '../interfaces/IHardwareGenerator.sol';
5 | import '../interfaces/IHardwareSVGs.sol';
6 | import '@openzeppelin/contracts/utils/Strings.sol';
7 |
8 | /// @dev Test Hardware Generator with less SVGs / less deploy overhead
9 | contract TestHardwareGenerator is IHardwareGenerator {
10 | using Strings for uint16;
11 |
12 | IHardwareSVGs immutable hardwareSVGs1;
13 | // needed to scrounge for a MYTHIC hardware
14 | IHardwareSVGs immutable hardwareSVGs29;
15 |
16 | struct TestHardwardSVGs {
17 | IHardwareSVGs hardwareSVGs1;
18 | IHardwareSVGs hardwareSVGs29;
19 | }
20 |
21 | constructor(TestHardwardSVGs memory svgs) {
22 | hardwareSVGs1 = svgs.hardwareSVGs1;
23 | hardwareSVGs29 = svgs.hardwareSVGs29;
24 | }
25 |
26 | function callHardwareSVGs(IHardwareSVGs target, uint16 hardware)
27 | internal
28 | view
29 | returns (IHardwareSVGs.HardwareData memory)
30 | {
31 | bytes memory functionSelector = abi.encodePacked('hardware_', uint16(hardware).toString(), '()');
32 |
33 | bool success;
34 | bytes memory result;
35 | (success, result) = address(target).staticcall(abi.encodeWithSelector(bytes4(keccak256(functionSelector))));
36 |
37 | return abi.decode(result, (IHardwareSVGs.HardwareData));
38 | }
39 |
40 | function generateHardware(uint16 hardware) external view override returns (IHardwareSVGs.HardwareData memory) {
41 | if (hardware <= 5) {
42 | return callHardwareSVGs(hardwareSVGs1, hardware);
43 | }
44 |
45 | // needed to scrounge for a MYTHIC hardware
46 | if (hardware == 96 || hardware == 97) {
47 | return callHardwareSVGs(hardwareSVGs29, hardware);
48 | }
49 |
50 | revert('invalid hardware selection');
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/deploy/01_deploy_field_generator.ts:
--------------------------------------------------------------------------------
1 | import { HardhatRuntimeEnvironment } from 'hardhat/types'
2 | import { DeployFunction } from 'hardhat-deploy/types'
3 | import fs from 'fs'
4 |
5 | const JSON_PATH = 'deploySVGs/deployedSVGs.json'
6 |
7 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
8 | const { deployer } = await hre.getNamedAccounts()
9 | const { deploy } = hre.deployments
10 |
11 | const deploymentArchive = JSON.parse(fs.readFileSync(JSON_PATH, { encoding: 'utf8' }))
12 |
13 | const colorHex = [
14 | 0xff007a, 0x6c28a2, 0xfe7fff, 0xd3d3d3, 0x323232, 0x78503c, 0x007fff, 0xb5000a, 0xff6b00, 0xffb300, 0x006351,
15 | 0xceff00,
16 | ]
17 |
18 | const colorNames = [
19 | 'Pink',
20 | 'Ultraviolet',
21 | 'Rose',
22 | 'Gray',
23 | 'Onyx',
24 | 'Brown',
25 | 'Sky',
26 | 'Crimson',
27 | 'Citrine',
28 | 'Gold',
29 | 'Evergreen',
30 | 'Hi-Vis',
31 | ]
32 |
33 | await deploy('FieldGenerator', {
34 | from: deployer,
35 | args: [colorHex, colorNames, deploymentArchive.fields],
36 | log: true,
37 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks
38 | maxFeePerGas: hre.ethers.BigNumber.from('95000000000'),
39 | })
40 | }
41 | export default func
42 | func.id = 'deploy_FieldGenerator' // id required to prevent reexecution
43 | func.tags = ['Shields']
44 |
--------------------------------------------------------------------------------
/deploy/02_deploy_hardware_generator.ts:
--------------------------------------------------------------------------------
1 | import { HardhatRuntimeEnvironment } from 'hardhat/types'
2 | import { DeployFunction } from 'hardhat-deploy/types'
3 | import fs from 'fs'
4 |
5 | const JSON_PATH = 'deploySVGs/deployedSVGs.json'
6 |
7 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
8 | const { deployer } = await hre.getNamedAccounts()
9 | const { deploy } = hre.deployments
10 |
11 | const svgDeploymentArchive = JSON.parse(fs.readFileSync(JSON_PATH, { encoding: 'utf8' }))
12 |
13 | await deploy('HardwareGenerator', {
14 | from: deployer,
15 | args: [svgDeploymentArchive.hardwares],
16 | log: true,
17 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks
18 | maxFeePerGas: hre.ethers.BigNumber.from('110000000000'),
19 | })
20 | }
21 | export default func
22 | func.id = 'deploy_HardwareGenerator' // id required to prevent reexecution
23 | func.tags = ['Shields']
24 |
--------------------------------------------------------------------------------
/deploy/03_deploy_frame_generator.ts:
--------------------------------------------------------------------------------
1 | import { HardhatRuntimeEnvironment } from 'hardhat/types'
2 | import { DeployFunction } from 'hardhat-deploy/types'
3 | import fs from 'fs'
4 |
5 | const JSON_PATH = 'deploySVGs/deployedSVGs.json'
6 |
7 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
8 | const { deployer } = await hre.getNamedAccounts()
9 | const { deploy } = hre.deployments
10 |
11 | const svgDeploymentArchive = JSON.parse(fs.readFileSync(JSON_PATH, { encoding: 'utf8' }))
12 |
13 | await deploy('FrameGenerator', {
14 | from: deployer,
15 | args: [svgDeploymentArchive.frames],
16 | log: true,
17 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks
18 | maxFeePerGas: hre.ethers.BigNumber.from('95000000000'),
19 | })
20 | }
21 | export default func
22 | func.id = 'deploy_FrameGenerator' // id required to prevent reexecution
23 | func.tags = ['Shields']
24 |
--------------------------------------------------------------------------------
/deploy/04_deploy_shieldbadgesvgs.ts:
--------------------------------------------------------------------------------
1 | import { HardhatRuntimeEnvironment } from 'hardhat/types'
2 | import { DeployFunction } from 'hardhat-deploy/types'
3 |
4 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
5 | const { deployer } = await hre.getNamedAccounts()
6 | const { deploy } = hre.deployments
7 |
8 | await deploy('ShieldBadgeSVGs', {
9 | from: deployer,
10 | log: true,
11 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks
12 | maxFeePerGas: hre.ethers.BigNumber.from('95000000000'),
13 | })
14 | }
15 | export default func
16 | func.id = 'deploy_ShieldBadgeSVGs' // id required to prevent reexecution
17 | // Question: Should this tag be renamed to Shields?
18 | func.tags = ['Shields']
19 |
--------------------------------------------------------------------------------
/deploy/05_deploy_emblem_weaver.ts:
--------------------------------------------------------------------------------
1 | import { HardhatRuntimeEnvironment } from 'hardhat/types'
2 | import { DeployFunction } from 'hardhat-deploy/types'
3 | import fs from 'fs'
4 |
5 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
6 | const { deployer } = await hre.getNamedAccounts()
7 | const { deploy } = hre.deployments
8 | const FieldGenerator = await hre.ethers.getContract('FieldGenerator')
9 | const HardwareGenerator = await hre.ethers.getContract('HardwareGenerator')
10 | const FrameGenerator = await hre.ethers.getContract('FrameGenerator')
11 | const ShieldBadgeSVGs = await hre.ethers.getContract('ShieldBadgeSVGs')
12 |
13 | await deploy('EmblemWeaver', {
14 | from: deployer,
15 | args: [FieldGenerator.address, HardwareGenerator.address, FrameGenerator.address, ShieldBadgeSVGs.address],
16 | log: true,
17 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks
18 | maxFeePerGas: hre.ethers.BigNumber.from('95000000000'),
19 | })
20 | }
21 | export default func
22 | func.id = 'deploy_EmblemWeaver' // id required to prevent reexecution
23 | // Question: Should this be renamed to Shields?
24 | func.tags = ['Shields']
25 |
--------------------------------------------------------------------------------
/deploy/06_deploy_shields.ts:
--------------------------------------------------------------------------------
1 | import { HardhatRuntimeEnvironment } from 'hardhat/types'
2 | import { DeployFunction } from 'hardhat-deploy/types'
3 | import fs from 'fs'
4 |
5 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
6 | const { deployer } = await hre.getNamedAccounts()
7 | const { deploy } = hre.deployments
8 | const EmblemWeaver = await hre.ethers.getContract('EmblemWeaver')
9 |
10 | await deploy('Shields', {
11 | from: deployer,
12 | args: [
13 | 'Shields',
14 | 'SHIELDS',
15 | EmblemWeaver.address,
16 | '0x42aaEEe1201EC5D1f3a3DCcc23AB8c01391d182d',
17 | '0x5e14ed9dCeE22ba758E8de482301028b261c4a14',
18 | ],
19 | log: true,
20 | autoMine: true, // speed up deployment on local network (ganache, hardhat), no effect on live networks
21 | maxFeePerGas: hre.ethers.BigNumber.from('95000000000'),
22 | })
23 | }
24 | export default func
25 | func.id = 'deploy_Shields' // id required to prevent reexecution
26 | func.tags = ['Shields']
27 |
--------------------------------------------------------------------------------
/deploy/07_transfer_ownership.ts:
--------------------------------------------------------------------------------
1 | import { HardhatRuntimeEnvironment } from 'hardhat/types'
2 | import { DeployFunction } from 'hardhat-deploy/types'
3 | import fs from 'fs'
4 | import { Shields } from '../typechain'
5 |
6 | const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
7 | const { deployer } = await hre.getNamedAccounts()
8 | const { deploy } = hre.deployments
9 | const shields = (await hre.ethers.getContract('Shields')) as Shields
10 |
11 | console.log(
12 | await shields.transferOwnership('0x42aaEEe1201EC5D1f3a3DCcc23AB8c01391d182d', {
13 | maxFeePerGas: hre.ethers.BigNumber.from('300000000000'),
14 | })
15 | )
16 | }
17 | export default func
18 | func.id = 'shields_premint' // id required to prevent reexecution
19 | func.tags = ['Shields']
20 |
--------------------------------------------------------------------------------
/deploySVGs/helpers.ts:
--------------------------------------------------------------------------------
1 | import web3Utils from 'web3-utils'
2 | import { ethers } from 'hardhat'
3 | import { ContractFactory } from 'ethers'
4 |
5 | export const SALT = '0x0000000000000000000000000000000000000000000000000000000000000000'
6 | export const SINGLETON_FACTORY_ADDRESS = '0xce0042B868300000d44A59004Da54A005ffdcf9f'
7 | export const SINGLETON_FACTORY_INTERFACE = new ethers.utils.Interface([
8 | 'function deploy(bytes memory _initCode, bytes32 _salt)',
9 | ])
10 |
11 | export type DeployedSVGs = {
12 | [contractName: string]: string
13 | }
14 |
15 | export type DeployedContracts = {
16 | [svgType: string]: DeployedSVGs
17 | }
18 |
19 | export type DeployedContractReceipt = {
20 | contractName: string
21 | address: string
22 | transactionHash?: string
23 | }
24 |
25 | export type DeployStatus = {
26 | deployed: boolean
27 | contractFactory: ContractFactory
28 | receipt: DeployedContractReceipt
29 | }
30 |
31 | export function constructDeploymentArchive(
32 | svgType: string,
33 | receipt: DeployedContractReceipt,
34 | deployedContracts: DeployedContracts
35 | ): DeployedContracts {
36 | svgType = `${svgType.toLowerCase()}s`
37 | deployedContracts[svgType][lowercaseFirst(receipt.contractName)] = receipt.address
38 | return deployedContracts
39 | }
40 |
41 | export function computeAddress(initcode: string): string {
42 | const codeHash = web3Utils.soliditySha3({ t: 'bytes', v: initcode })
43 | if (!codeHash) {
44 | throw 'No codehash'
45 | }
46 | const addressAsBytes32 = web3Utils.soliditySha3(
47 | { t: 'uint8', v: 255 }, // 0xff
48 | { t: 'address', v: SINGLETON_FACTORY_ADDRESS },
49 | { t: 'bytes32', v: SALT },
50 | { t: 'bytes32', v: codeHash }
51 | )
52 | return `0x${addressAsBytes32!.slice(26, 66)}`
53 | }
54 |
55 | function lowercaseFirst(str: string): string {
56 | return str[0].toLowerCase() + str.slice(1)
57 | }
58 |
--------------------------------------------------------------------------------
/deployments/goerli/.chainId:
--------------------------------------------------------------------------------
1 | 5
--------------------------------------------------------------------------------
/deployments/mainnet/.chainId:
--------------------------------------------------------------------------------
1 | 1
--------------------------------------------------------------------------------
/deployments/rinkeby/.chainId:
--------------------------------------------------------------------------------
1 | 4
--------------------------------------------------------------------------------
/fields.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Area-Technology/shields-contracts/f0d9058bf82f394b84bdaa67f466766a7258637c/fields.txt
--------------------------------------------------------------------------------
/hardhat.config.ts:
--------------------------------------------------------------------------------
1 | import 'hardhat-deploy'
2 | import 'hardhat-typechain'
3 | import '@nomiclabs/hardhat-ethers'
4 | import '@nomiclabs/hardhat-waffle'
5 | import '@nomiclabs/hardhat-etherscan'
6 | import dotenv from 'dotenv'
7 | dotenv.config()
8 |
9 | const DEFAULT_COMPILER_SETTINGS = {
10 | version: '0.8.9',
11 | settings: {
12 | optimizer: {
13 | enabled: false,
14 | },
15 | metadata: {
16 | // do not include the metadata hash, since this is machine dependent
17 | // and we want all generated code to be deterministic
18 | // https://docs.soliditylang.org/en/v0.7.6/metadata.html
19 | bytecodeHash: 'none',
20 | },
21 | },
22 | }
23 |
24 | const OPTIMIZED_COMPILER_SETTINGS = {
25 | version: '0.8.9',
26 | settings: {
27 | optimizer: {
28 | enabled: true,
29 | runs: 1_000_000,
30 | },
31 | metadata: {
32 | // do not include the metadata hash, since this is machine dependent
33 | // and we want all generated code to be deterministic
34 | // https://docs.soliditylang.org/en/v0.7.6/metadata.html
35 | bytecodeHash: 'none',
36 | },
37 | },
38 | }
39 |
40 | export default {
41 | networks: {
42 | hardhat: {
43 | allowUnlimitedContractSize: false,
44 | },
45 | mainnet: {
46 | url: `https://mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`,
47 | accounts: [process.env.MAINNET_DEPLOYER],
48 | },
49 | ropsten: {
50 | url: `https://ropsten.infura.io/v3/${process.env.INFURA_API_KEY}`,
51 | },
52 | rinkeby: {
53 | url: `https://rinkeby.infura.io/v3/${process.env.INFURA_API_KEY}`,
54 | accounts: [process.env.DEPLOYER],
55 | },
56 | goerli: {
57 | url: `https://goerli.infura.io/v3/${process.env.INFURA_API_KEY}`,
58 | accounts: [process.env.DEPLOYER],
59 | },
60 | kovan: {
61 | url: `https://kovan.infura.io/v3/${process.env.INFURA_API_KEY}`,
62 | },
63 | },
64 | namedAccounts: {
65 | deployer: 0,
66 | },
67 | etherscan: {
68 | // Your API key for Etherscan
69 | // Obtain one at https://etherscan.io/
70 | apiKey: process.env.ETHERSCAN_API_KEY,
71 | },
72 | solidity: {
73 | compilers: [DEFAULT_COMPILER_SETTINGS],
74 | overrides: {
75 | 'contracts/Shields.sol': OPTIMIZED_COMPILER_SETTINGS,
76 | 'contracts/ShieldDescriptor.sol': OPTIMIZED_COMPILER_SETTINGS,
77 | 'contracts/FieldGenerator.sol': OPTIMIZED_COMPILER_SETTINGS,
78 | 'contracts/FrameGenerator.sol': OPTIMIZED_COMPILER_SETTINGS,
79 | 'contracts/HardwareGenerator.sol': OPTIMIZED_COMPILER_SETTINGS,
80 | },
81 | },
82 | mocha: {
83 | timeout: 60000,
84 | },
85 | }
86 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "shields",
3 | "description": "Customizable Shield NFTs",
4 | "license": "GPL-3.0-or-later",
5 | "publishConfig": {
6 | "access": "restricted"
7 | },
8 | "version": "1.0.0-alpha.0",
9 | "homepage": "",
10 | "keywords": [
11 | "uniswap",
12 | "nft",
13 | "swap"
14 | ],
15 | "repository": {
16 | "type": "git",
17 | "url": "https://github.com/johncpalmer/ugp-crest-contracts"
18 | },
19 | "files": [
20 | "contracts/interfaces",
21 | "contracts/libraries",
22 | "artifacts/contracts/**/*.json",
23 | "!artifacts/contracts/**/*.dbg.json"
24 | ],
25 | "engines": {
26 | "node": ">=14"
27 | },
28 | "dependencies": {
29 | "@openzeppelin/contracts": "v4.4.2",
30 | "base64-sol": "1.0.1"
31 | },
32 | "devDependencies": {
33 | "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers",
34 | "@nomiclabs/hardhat-etherscan": "^2.1.1",
35 | "@nomiclabs/hardhat-waffle": "^2.0.1",
36 | "@typechain/ethers-v5": "^4.0.0",
37 | "@types/chai": "^4.2.6",
38 | "@types/mocha": "^5.2.7",
39 | "chai": "^4.2.0",
40 | "dotenv": "^10.0.0",
41 | "ethereum-waffle": "^3.0.2",
42 | "ethers": "^5.0.8",
43 | "hardhat": "^2.2.0",
44 | "hardhat-deploy": "^0.9.6",
45 | "hardhat-typechain": "^0.3.5",
46 | "mocha": "^6.2.2",
47 | "mocha-chai-jest-snapshot": "^1.1.0",
48 | "prettier": "^2.0.5",
49 | "prettier-plugin-solidity": "^1.0.0-alpha.59",
50 | "solhint": "^3.2.1",
51 | "solhint-plugin-prettier": "^0.0.5",
52 | "ts-generator": "^0.1.1",
53 | "ts-node": "^8.5.4",
54 | "typechain": "^4.0.0",
55 | "typescript": "^3.7.3",
56 | "web3-utils": "^1.3.6"
57 | },
58 | "scripts": {
59 | "compile": "hardhat compile",
60 | "test": "hardhat test",
61 | "deploy": "hardhat deploy --network",
62 | "deploySVGs": "hardhat run deploySVGs/deployFieldSVGs.ts --network"
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/test/FieldSVGs.spec.ts:
--------------------------------------------------------------------------------
1 | import { FieldGenerator, FieldSVGs1 } from '../typechain'
2 | import { ethers, waffle } from 'hardhat'
3 | import { expect } from './shared/expect'
4 | import snapshotGasCost from './shared/snapshotGasCost'
5 | import fs from 'fs'
6 | import encodeColors from './shared/encodeColors'
7 | import { fieldColors, titles } from './shared/colors'
8 | import { BigNumber, BigNumberish } from 'ethers'
9 | import deployFieldGenerator from './shared/deployFieldGenerator'
10 |
11 | describe('FieldSVGs', async () => {
12 | let fields: FieldGenerator
13 | let fieldSVGs1: FieldSVGs1
14 |
15 | describe('constructor', () => {
16 | it('deployment gas', async () => {
17 | const asGasSnapshot = true
18 | await deployFieldGenerator(asGasSnapshot)
19 | })
20 |
21 | it('bytecode size', async () => {
22 | const contract = await deployFieldGenerator()
23 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot()
24 | })
25 | })
26 |
27 | describe('IFieldSVGs deployment', () => {
28 | for (let i = 1; i <= 24; i++) {
29 | it(`FieldSVGs${i} has gas`, async () => {
30 | await snapshotGasCost((await ethers.getContractFactory(`FieldSVGs${i}`)).deploy())
31 | })
32 |
33 | it(`FieldSVGs${i} has bytecode`, async () => {
34 | const contract = await (await ethers.getContractFactory(`FieldSVGs${i}`)).deploy()
35 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot()
36 | })
37 | }
38 | })
39 |
40 | describe.skip('SVG Generation', () => {
41 | beforeEach(async () => {
42 | const fieldSVGs1 = (await (await ethers.getContractFactory('FieldSVGs1')).deploy()) as FieldSVGs1
43 | const fieldSVGs2 = (await (await ethers.getContractFactory('FieldSVGs2')).deploy()) as FieldSVGs1
44 | const contract = await (
45 | await ethers.getContractFactory('FieldGenerator')
46 | ).deploy(fieldColors, titles, fieldSVGs1.address, fieldSVGs2.address)
47 | })
48 |
49 | it('returns the correct field_one_color svg string', async () => {
50 | const color: [BigNumberish, BigNumberish, BigNumberish, BigNumberish] = [
51 | BigNumber.from(0xdeadbe),
52 | BigNumber.from(0xdeadbe),
53 | BigNumber.from(0xdeadde),
54 | BigNumber.from(0xddadbe),
55 | ]
56 |
57 | const svg = await fields.generateField(0, color)
58 | expect(svg).toMatchSnapshot()
59 | })
60 |
61 | it('returns the correct field_two_colors svg string', async () => {
62 | const color = encodeColors([0xdeadbe, 0xc1c1c1])
63 |
64 | const svg = await fields.generateField(2, color)
65 | expect(svg).toMatchSnapshot()
66 | })
67 |
68 | it('returns the correct field_three_colors svg string', async () => {
69 | const color = encodeColors([0xdeadbe, 0xc1c1c1, 0xf234ab])
70 |
71 | const svg = await fields.generateField(293, color)
72 | expect(svg).toMatchSnapshot()
73 | })
74 |
75 | it('returns the correct field_four_colors svg string', async () => {
76 | const color = encodeColors([0xdeadbe, 0xc1c1c1, 0xf234ab, 0x889933])
77 |
78 | const svg = await fields.generateField(299, color)
79 | expect(svg).toMatchSnapshot()
80 | })
81 | })
82 | })
83 |
--------------------------------------------------------------------------------
/test/FrameSVGs.spec.ts:
--------------------------------------------------------------------------------
1 | import { FrameGenerator, FrameSVGs1 } from '../typechain'
2 | import { ethers, waffle } from 'hardhat'
3 | import { expect } from './shared/expect'
4 | import snapshotGasCost from './shared/snapshotGasCost'
5 | import deployFrameGenerator from './shared/deployFrameGenerator'
6 | import fs from 'fs'
7 |
8 | describe('FrameGenerator', async () => {
9 | let frames: FrameGenerator
10 |
11 | describe('constructor', () => {
12 | it('deployment gas', async () => {
13 | const asGasSnapshot = true
14 | await deployFrameGenerator(asGasSnapshot)
15 | })
16 |
17 | it('bytecode size', async () => {
18 | const contract = (await deployFrameGenerator()) as FrameGenerator
19 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot()
20 | })
21 | })
22 |
23 | describe('IFrameSVGs deployment', () => {
24 | for (let i = 1; i <= 2; i++) {
25 | it(`FrameSVGs${i} has gas`, async () => {
26 | await snapshotGasCost((await ethers.getContractFactory(`FrameSVGs${i}`)).deploy())
27 | })
28 |
29 | it(`FrameSVGs${i} has bytecode`, async () => {
30 | const contract = await (await ethers.getContractFactory(`FrameSVGs${i}`)).deploy()
31 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot()
32 | })
33 | }
34 | })
35 |
36 | describe('SVG Generation', () => {
37 | it('returns the correct frame svg string', async () => {
38 | frames = (await deployFrameGenerator()) as FrameGenerator
39 | const frame = await frames.generateFrame(3)
40 | expect(frame).toMatchSnapshot()
41 | const svg = ``
42 | fs.writeFileSync('./test/__snapshots__/svgs/frame.svg', svg)
43 | })
44 | })
45 | })
46 |
--------------------------------------------------------------------------------
/test/HardwareSVGs.spec.ts:
--------------------------------------------------------------------------------
1 | import { HardwareGenerator, HardwareSVGs1 } from '../typechain'
2 | import { ethers, waffle } from 'hardhat'
3 | import { expect } from './shared/expect'
4 | import snapshotGasCost from './shared/snapshotGasCost'
5 | import deployHardwareGenerator from './shared/deployHardwareGenerator'
6 | import fs from 'fs'
7 |
8 | describe('HardwareGenerator', async () => {
9 | let hardwares: HardwareGenerator
10 |
11 | describe('constructor', () => {
12 | it('deployment gas', async () => {
13 | const asGasSnapshot = true
14 | await deployHardwareGenerator(asGasSnapshot)
15 | })
16 |
17 | it('bytecode size', async () => {
18 | const contract = (await deployHardwareGenerator()) as HardwareGenerator
19 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot()
20 | })
21 | })
22 |
23 | describe('IHardwareSVGs deployment', () => {
24 | for (let i = 1; i <= 38; i++) {
25 | it(`HardwareSVGs${i} has gas`, async () => {
26 | await snapshotGasCost((await ethers.getContractFactory(`HardwareSVGs${i}`)).deploy())
27 | })
28 |
29 | it(`HardwareSVGs${i} has bytecode`, async () => {
30 | const contract = await (await ethers.getContractFactory(`HardwareSVGs${i}`)).deploy()
31 | expect(((await contract.provider.getCode(contract.address)).length - 2) / 2).to.matchSnapshot()
32 | })
33 | }
34 | })
35 |
36 | describe('SVG Generation', () => {
37 | it('returns the correct hardware svg string', async () => {
38 | hardwares = (await deployHardwareGenerator()) as HardwareGenerator
39 | const hardware = await hardwares.generateHardware(0)
40 | expect(hardware).toMatchSnapshot()
41 | const svg = ``
42 | fs.writeFileSync('./test/__snapshots__/svgs/hardware.svg', svg)
43 | })
44 | })
45 | })
46 |
--------------------------------------------------------------------------------
/test/__snapshots__/EmblemWeaver.spec.ts.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`EmblemWeaver constructor deployment gas 1`] = `2622206`;
4 |
5 | exports[`EmblemWeaver constructor has bytecode size 1`] = `12692`;
6 |
--------------------------------------------------------------------------------
/test/__snapshots__/ShieldDescriptor.spec.ts.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`EmblemWeaver constructor deployment gas 1`] = `2028334`;
4 |
5 | exports[`EmblemWeaver constructor has bytecode size 1`] = `12692`;
6 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Area-Technology/shields-contracts/f0d9058bf82f394b84bdaa67f466766a7258637c/test/__snapshots__/svgs/.DS_Store
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/fields/000_Perfect.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/fields/001_Per Pale.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/fields/068_Canton.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/fields/069_Canton Sinister.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/fields/070_Chief.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/fields/077_Chief Triangular.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/fields/111_Pile.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/fields/117_Gyron.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/fields/162_Billet.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/frames/000_.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/000_Bushing Hammer.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/001_Shovel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/002_Screw.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/003_Flathead Screwdriver.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/004_Pen Nib.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/005_Scissors.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/008_Tongs.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/009_Compass and Triangle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/010_Magnifying Glass.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/011_Shears.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/014_Tuning Fork.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/015_Mallet with Chisels in Saltire.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/016_Hammer and Compass.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/018_Book.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/019_Calipers.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/020_Three Nails.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/021_Awl.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/022_French Key Wrench.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/024_Anvil.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/027_Jewelers Loupe.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/029_Cauldron.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/031_Lug Wrench and Four Lug Nuts.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/033_Rudder.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/034_Gavel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/037_Triskele Tracery.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/037_Triskele.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/039_Keyhole.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/040_Pitcher.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/054_Stack.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/055_Orb.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/056_Command in Canton.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/057_Three Chalices.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/058_Three Brushes.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/059_Three Writing Pens.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/060_Lead Holder and Twin Blades.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/065_Three Bells in Chief.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/066_Three Suns in Chief.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/068_Two Suns.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/069_Four Suns.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/070_Two Books.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/082_Horse-head Gables.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/105_Chain Palewise.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/109_Bordure Plate.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/110_Inverted Pall Plate.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/__snapshots__/svgs/hardware/120_Three Shields.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/shared/buildShield.ts:
--------------------------------------------------------------------------------
1 | import { Shields } from '../../typechain'
2 | import { BigNumber, BigNumberish, ContractTransaction } from 'ethers'
3 | import { ethers } from 'hardhat'
4 |
5 | type ShieldBuilt = {
6 | tx: ContractTransaction
7 | tokenId: string
8 | }
9 |
10 | export async function buildShield(
11 | shields: Shields,
12 | params: {
13 | field: number
14 | hardware: number
15 | frame: number
16 | colors: [BigNumberish, BigNumberish, BigNumberish, BigNumberish]
17 | fee: BigNumber
18 | to: string
19 | }
20 | ): Promise {
21 | const mintTx = await (
22 | await shields.mint(params.to, 1, { value: BigNumber.from(ethers.utils.parseEther('0.15')) })
23 | ).wait()
24 | const tokenId = mintTx.events![0].args!.tokenId
25 | const tx = await shields.build(params.field, params.hardware, params.frame, params.colors, tokenId, {
26 | value: params.fee,
27 | })
28 | return { tx, tokenId }
29 | }
30 |
--------------------------------------------------------------------------------
/test/shared/colors.ts:
--------------------------------------------------------------------------------
1 | const colorMap = new Map([
2 | [0xfc03a5, 'radical red'],
3 | [0x5632a8, 'perfect pink'],
4 | [0x112233, 'bloo'],
5 | [0xaabbff, 'gothic green'],
6 | ])
7 | const fieldColors = Array.from(colorMap.keys())
8 | const titles = Array.from(colorMap.values())
9 |
10 | export { colorMap, fieldColors, titles }
11 |
--------------------------------------------------------------------------------
/test/shared/deployFrameGenerator.ts:
--------------------------------------------------------------------------------
1 | import { ethers } from 'hardhat'
2 | import { FrameGenerator, FrameSVGs1 } from '../../typechain'
3 | import snapshotGasCost from './snapshotGasCost'
4 |
5 | export default async function deployFrameGenerator(asGasSnapshot?: boolean) {
6 | const frameSVGs1 = (await (await ethers.getContractFactory('FrameSVGs1')).deploy()) as FrameSVGs1
7 | const frameSVGs2 = (await (await ethers.getContractFactory('FrameSVGs2')).deploy()) as FrameSVGs1
8 |
9 | if (!!asGasSnapshot) {
10 | await snapshotGasCost(
11 | (
12 | await ethers.getContractFactory('FrameGenerator')
13 | ).deploy({ frameSVGs1: frameSVGs1.address, frameSVGs2: frameSVGs2.address })
14 | )
15 | }
16 |
17 | const contract = (await (
18 | await ethers.getContractFactory('FrameGenerator')
19 | ).deploy({ frameSVGs1: frameSVGs1.address, frameSVGs2: frameSVGs2.address })) as FrameGenerator
20 | return contract
21 | }
22 |
--------------------------------------------------------------------------------
/test/shared/deployTestFieldGenerator.ts:
--------------------------------------------------------------------------------
1 | import { ethers } from 'hardhat'
2 | import { FieldGenerator, FieldSVGs1 } from '../../typechain'
3 | import { fieldColors, titles } from './colors'
4 | import snapshotGasCost from './snapshotGasCost'
5 |
6 | export default async function deployTestFieldGenerator(asGasSnapshot?: boolean) {
7 | const fieldSVGs1 = (await (await ethers.getContractFactory('FieldSVGs1')).deploy()) as FieldSVGs1
8 | const fieldSVGs2 = (await (await ethers.getContractFactory('FieldSVGs2')).deploy()) as FieldSVGs1
9 |
10 | const svgs = {
11 | fieldSVGs1: fieldSVGs1.address,
12 | fieldSVGs2: fieldSVGs2.address,
13 | }
14 |
15 | if (!!asGasSnapshot) {
16 | await snapshotGasCost((await ethers.getContractFactory('TestFieldGenerator')).deploy(fieldColors, titles, svgs))
17 | }
18 |
19 | const contract = (await (
20 | await ethers.getContractFactory('TestFieldGenerator')
21 | ).deploy(fieldColors, titles, svgs)) as FieldGenerator
22 | return contract
23 | }
24 |
--------------------------------------------------------------------------------
/test/shared/deployTestHardwareGenerator.ts:
--------------------------------------------------------------------------------
1 | import { ethers } from 'hardhat'
2 | import { HardwareGenerator, HardwareSVGs1 } from '../../typechain'
3 | import snapshotGasCost from './snapshotGasCost'
4 |
5 | export default async function deployTestHardwareGenerator(asGasSnapshot?: boolean) {
6 | const hardwareSVGs1 = (await (await ethers.getContractFactory('HardwareSVGs1')).deploy()) as HardwareSVGs1
7 | const hardwareSVGs29 = (await (await ethers.getContractFactory('HardwareSVGs29')).deploy()) as HardwareSVGs1
8 |
9 | const svgs = {
10 | hardwareSVGs1: hardwareSVGs1.address,
11 | hardwareSVGs29: hardwareSVGs29.address,
12 | }
13 |
14 | if (!!asGasSnapshot) {
15 | await snapshotGasCost((await ethers.getContractFactory('TestHardwareGenerator')).deploy(svgs))
16 | }
17 |
18 | const contract = (await (await ethers.getContractFactory('TestHardwareGenerator')).deploy(svgs)) as HardwareGenerator
19 | return contract
20 | }
21 |
--------------------------------------------------------------------------------
/test/shared/encodeColors.ts:
--------------------------------------------------------------------------------
1 | import { ethers } from 'hardhat'
2 | import { BigNumberish } from 'ethers'
3 |
4 | export default function encodeColors(
5 | colors: number[] | BigNumberish[]
6 | ): [BigNumberish, BigNumberish, BigNumberish, BigNumberish] {
7 | let colorArray: [BigNumberish, BigNumberish, BigNumberish, BigNumberish] = [0, 0, 0, 0]
8 |
9 | colors.forEach((color, index) => {
10 | colorArray[index] = color
11 | })
12 |
13 | return colorArray
14 | }
15 |
--------------------------------------------------------------------------------
/test/shared/expect.ts:
--------------------------------------------------------------------------------
1 | import { expect, use } from 'chai'
2 | import { solidity } from 'ethereum-waffle'
3 | import { jestSnapshotPlugin } from 'mocha-chai-jest-snapshot'
4 |
5 | use(solidity)
6 | use(jestSnapshotPlugin())
7 |
8 | export { expect }
9 |
--------------------------------------------------------------------------------
/test/shared/extractJSONFromURI.ts:
--------------------------------------------------------------------------------
1 | type attribute = {
2 | trait_type: string
3 | value: string
4 | }
5 |
6 | export function extractJSONFromURI(uri: string): {
7 | name: string
8 | description: string
9 | image: string
10 | attributes: Array
11 | } {
12 | const encodedJSON = uri.substr('data:application/json;base64,'.length)
13 | const decodedJSON = Buffer.from(encodedJSON, 'base64').toString('utf8')
14 | return JSON.parse(decodedJSON)
15 | }
16 |
--------------------------------------------------------------------------------
/test/shared/printSVGToSnapshots.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs'
2 |
3 | export function printSVGToSnapshots(type: string, title: string, svgString: string) {
4 | fs.writeFileSync(`./test/__snapshots__/svgs/${type}/${title}.svg`, svgString)
5 | }
6 |
--------------------------------------------------------------------------------
/test/shared/snapshotGasCost.ts:
--------------------------------------------------------------------------------
1 | import { TransactionReceipt, TransactionResponse } from '@ethersproject/abstract-provider'
2 | import { expect } from './expect'
3 | import { Contract, BigNumber, ContractTransaction } from 'ethers'
4 |
5 | export default async function snapshotGasCost(
6 | x:
7 | | TransactionResponse
8 | | Promise
9 | | ContractTransaction
10 | | Promise
11 | | TransactionReceipt
12 | | Promise
13 | | BigNumber
14 | | Contract
15 | | Promise
16 | ): Promise {
17 | const resolved = await x
18 | if ('deployTransaction' in resolved) {
19 | const receipt = await resolved.deployTransaction.wait()
20 | expect(receipt.gasUsed.toNumber()).toMatchSnapshot()
21 | } else if ('wait' in resolved) {
22 | const waited = await resolved.wait()
23 | expect(waited.gasUsed.toNumber()).toMatchSnapshot()
24 | } else if (BigNumber.isBigNumber(resolved)) {
25 | expect(resolved.toNumber()).toMatchSnapshot()
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2018",
4 | "module": "commonjs",
5 | "strict": true,
6 | "esModuleInterop": true,
7 | "outDir": "dist",
8 | "typeRoots": ["./typechain", "./node_modules/@types"],
9 | "types": ["@nomiclabs/hardhat-ethers", "@nomiclabs/hardhat-waffle"]
10 | },
11 | "include": ["./test"],
12 | "files": ["./hardhat.config.ts"]
13 | }
14 |
--------------------------------------------------------------------------------